mirror of
https://github.com/boostorg/python.git
synced 2026-01-26 18:52:26 +00:00
implement static data members
[SVN r18157]
This commit is contained in:
@@ -290,19 +290,28 @@ class class_ : public objects::class_base
|
||||
//
|
||||
// Data member access
|
||||
//
|
||||
template <class D, class B>
|
||||
self& def_readonly(char const* name, D B::*pm_)
|
||||
template <class D>
|
||||
self& def_readonly(char const* name, D const& d)
|
||||
{
|
||||
D T::*pm = pm_;
|
||||
this->add_property(name, make_getter(pm));
|
||||
return *this;
|
||||
return this->def_readonly_impl(name, d, 0);
|
||||
}
|
||||
|
||||
template <class D, class B>
|
||||
self& def_readwrite(char const* name, D B::*pm_)
|
||||
template <class D>
|
||||
self& def_readwrite(char const* name, D const& d)
|
||||
{
|
||||
D T::*pm = pm_;
|
||||
return this->add_property(name, make_getter(pm), make_setter(pm));
|
||||
return this->def_readwrite_impl(name, d, 0);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readonly(char const* name, D& d)
|
||||
{
|
||||
return this->def_readonly_impl(name, d, 0);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readwrite(char const* name, D& d)
|
||||
{
|
||||
return this->def_readwrite_impl(name, d, 0);
|
||||
}
|
||||
|
||||
// Property creation
|
||||
@@ -334,6 +343,34 @@ class class_ : public objects::class_base
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get>
|
||||
self& add_static_property(char const* name, Get fget)
|
||||
{
|
||||
base::add_static_property(
|
||||
name
|
||||
, object(
|
||||
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(fget)
|
||||
)
|
||||
);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get, class Set>
|
||||
self& add_static_property(char const* name, Get fget, Set fset)
|
||||
{
|
||||
base::add_static_property(
|
||||
name
|
||||
, object(
|
||||
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(fget)
|
||||
)
|
||||
, object(
|
||||
detail::member_function_cast<T,Set>::stage1(fset).stage2((T*)0).stage3(fset)
|
||||
)
|
||||
);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
self& setattr(char const* name, U const& x)
|
||||
{
|
||||
@@ -362,6 +399,32 @@ class class_ : public objects::class_base
|
||||
}
|
||||
private: // helper functions
|
||||
|
||||
template <class D, class B>
|
||||
self& def_readonly_impl(char const* name, D B::*pm_, int)
|
||||
{
|
||||
D T::*pm = pm_;
|
||||
return this->add_property(name, make_getter(pm));
|
||||
}
|
||||
|
||||
template <class D, class B>
|
||||
self& def_readwrite_impl(char const* name, D B::*pm_, int)
|
||||
{
|
||||
D T::*pm = pm_;
|
||||
return this->add_property(name, make_getter(pm), make_setter(pm));
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readonly_impl(char const* name, D& d, ...)
|
||||
{
|
||||
return this->add_static_property(name, make_getter(d));
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readwrite_impl(char const* name, D& d, ...)
|
||||
{
|
||||
return this->add_static_property(name, make_getter(d), make_setter(d));
|
||||
}
|
||||
|
||||
inline void register_() const;
|
||||
|
||||
//
|
||||
|
||||
@@ -18,12 +18,16 @@
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/add_const.hpp>
|
||||
# include <boost/type_traits/add_reference.hpp>
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
|
||||
# include <boost/mpl/apply_if.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/identity.hpp>
|
||||
|
||||
# include <boost/bind.hpp>
|
||||
|
||||
@@ -71,74 +75,169 @@ namespace detail
|
||||
}
|
||||
};
|
||||
|
||||
template <class Data, class Policies>
|
||||
struct datum
|
||||
{
|
||||
static PyObject* get(Data *p, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
// find the result converter
|
||||
typedef typename Policies::result_converter result_converter;
|
||||
typedef typename boost::add_reference<Data>::type source;
|
||||
typename mpl::apply1<result_converter,source>::type cr;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
PyObject* result = cr( *p );
|
||||
|
||||
return policies.postcall(args_, result);
|
||||
}
|
||||
|
||||
static PyObject* set(Data* p, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
typedef typename add_const<Data>::type target1;
|
||||
typedef typename add_reference<target1>::type target;
|
||||
arg_from_python<target> c0(PyTuple_GET_ITEM(args_, 0));
|
||||
|
||||
if (!c0.convertible()) return 0;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
*p = c0(PyTuple_GET_ITEM(args_, 0));
|
||||
|
||||
return policies.postcall(args_, detail::none());
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct default_getter_by_ref
|
||||
: mpl::and_<
|
||||
mpl::bool_<
|
||||
to_python_value<
|
||||
typename add_reference<typename add_const<T>::type>::type
|
||||
>::uses_registry
|
||||
>
|
||||
, is_reference_to_class<
|
||||
typename add_reference<typename add_const<T>::type>::type
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// If it's a regular class type (not an object manager or other
|
||||
// type for which we have to_python specializations, use
|
||||
// return_internal_reference so that we can do things like
|
||||
// x.y.z = 1
|
||||
// and get the right result.
|
||||
template <class T>
|
||||
struct default_getter_policy
|
||||
struct default_member_getter_policy
|
||||
: mpl::if_<
|
||||
default_getter_by_ref<T>
|
||||
, return_internal_reference<>
|
||||
, return_value_policy<return_by_value>
|
||||
>
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
struct default_datum_getter_policy
|
||||
: mpl::if_<
|
||||
default_getter_by_ref<T>
|
||||
, return_value_policy<reference_existing_object>
|
||||
, return_value_policy<return_by_value>
|
||||
>
|
||||
{};
|
||||
|
||||
template <class D, class Policies>
|
||||
inline object make_getter(D* p, Policies const& policies, int)
|
||||
{
|
||||
typedef typename add_reference<
|
||||
typename add_const<T>::type
|
||||
>::type t_cref;
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::datum<D,Policies>::get, p, _1, _2
|
||||
, policies)
|
||||
, 0);
|
||||
}
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, by_ref = to_python_value<t_cref>::uses_registry
|
||||
&& is_reference_to_class<t_cref>::value);
|
||||
template <class D>
|
||||
inline object make_getter(D* p, not_specified, long)
|
||||
{
|
||||
typedef typename default_datum_getter_policy<D>::type policies;
|
||||
return make_getter(p, policies(), 0L);
|
||||
}
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
by_ref
|
||||
, return_internal_reference<>
|
||||
, return_value_policy<return_by_value>
|
||||
>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class C, class D>
|
||||
object make_getter(D C::*pm)
|
||||
{
|
||||
typedef typename detail::default_getter_policy<D>::type policy;
|
||||
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,policy>::get, pm, _1, _2
|
||||
, policy())
|
||||
, 1);
|
||||
|
||||
}
|
||||
|
||||
template <class C, class D, class Policies>
|
||||
object make_getter(D C::*pm, Policies const& policies)
|
||||
{
|
||||
template <class C, class D, class Policies>
|
||||
inline object make_getter(D C::*pm, Policies const& policies, int)
|
||||
{
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,Policies>::get, pm, _1, _2
|
||||
, policies)
|
||||
, 1);
|
||||
}
|
||||
|
||||
template <class C, class D>
|
||||
inline object make_getter(D C::*pm, not_specified, long)
|
||||
{
|
||||
typedef typename default_member_getter_policy<D>::type policies;
|
||||
return make_getter(pm, policies(), 0L);
|
||||
}
|
||||
|
||||
template <class D, class Policies>
|
||||
inline object make_getter(D& d, Policies const& policies, ...)
|
||||
{
|
||||
return detail::make_getter(&d, policies, 0L);
|
||||
}
|
||||
|
||||
template <class D, class Policies>
|
||||
inline object make_setter(D* p, Policies const& policies, long)
|
||||
{
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::datum<D,Policies>::set, p, _1, _2
|
||||
, policies)
|
||||
, 1);
|
||||
}
|
||||
|
||||
template <class C, class D, class Policies>
|
||||
inline object make_setter(D C::*pm, Policies const& policies, long)
|
||||
{
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,Policies>::set, pm, _1, _2
|
||||
, policies)
|
||||
, 2);
|
||||
}
|
||||
|
||||
template <class D, class Policies>
|
||||
inline object make_setter(D& x, Policies const& policies, ...)
|
||||
{
|
||||
return detail::make_setter(&x, policies, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
template <class C, class D>
|
||||
object make_setter(D C::*pm)
|
||||
template <class D, class Policies>
|
||||
inline object make_getter(D& d, Policies const& policies)
|
||||
{
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,default_call_policies>::set, pm, _1, _2
|
||||
, default_call_policies())
|
||||
, 2);
|
||||
return detail::make_getter(d, policies, 0L);
|
||||
}
|
||||
|
||||
template <class C, class D, class Policies>
|
||||
object make_setter(D C::*pm, Policies const& policies)
|
||||
template <class D>
|
||||
inline object make_getter(D& x)
|
||||
{
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,Policies>::set, pm, _1, _2
|
||||
, policies)
|
||||
, 2);
|
||||
return detail::make_getter(x, detail::not_specified(), 0L);
|
||||
}
|
||||
|
||||
template <class D, class Policies>
|
||||
inline object make_setter(D& x, Policies const& policies)
|
||||
{
|
||||
return detail::make_setter(x, policies, 0L);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
inline object make_setter(D& x)
|
||||
{
|
||||
return detail::make_setter(x, default_call_policies(), 0L);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // DATA_MEMBERS_DWA2002328_HPP
|
||||
|
||||
@@ -41,16 +41,160 @@ instance_holder::~instance_holder()
|
||||
{
|
||||
}
|
||||
|
||||
// This is copied from typeobject.c in the Python sources. Even though
|
||||
// class_metatype_object doesn't set Py_TPFLAGS_HAVE_GC, that bit gets
|
||||
// filled in by the base class initialization process in
|
||||
// PyType_Ready(). However, tp_is_gc is *not* copied from the base
|
||||
// type, making it assume that classes are GC-able even if (like
|
||||
// class_type_object) they're statically allocated.
|
||||
static int
|
||||
type_is_gc(PyTypeObject *python_type)
|
||||
extern "C"
|
||||
{
|
||||
return python_type->tp_flags & Py_TPFLAGS_HEAPTYPE;
|
||||
// This is copied from typeobject.c in the Python sources. Even though
|
||||
// class_metatype_object doesn't set Py_TPFLAGS_HAVE_GC, that bit gets
|
||||
// filled in by the base class initialization process in
|
||||
// PyType_Ready(). However, tp_is_gc is *not* copied from the base
|
||||
// type, making it assume that classes are GC-able even if (like
|
||||
// class_type_object) they're statically allocated.
|
||||
static int
|
||||
type_is_gc(PyTypeObject *python_type)
|
||||
{
|
||||
return python_type->tp_flags & Py_TPFLAGS_HEAPTYPE;
|
||||
}
|
||||
|
||||
// This is also copied from the Python sources. We can't implement
|
||||
// static_data as a subclass property effectively without it.
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject *prop_get;
|
||||
PyObject *prop_set;
|
||||
PyObject *prop_del;
|
||||
PyObject *prop_doc;
|
||||
} propertyobject;
|
||||
|
||||
static PyObject *
|
||||
static_data_descr_get(PyObject *self, PyObject *obj, PyObject * /*type*/)
|
||||
{
|
||||
propertyobject *gs = (propertyobject *)self;
|
||||
|
||||
return PyObject_CallFunction(gs->prop_get, "()");
|
||||
}
|
||||
|
||||
static int
|
||||
static_data_descr_set(PyObject *self, PyObject *obj, PyObject *value)
|
||||
{
|
||||
propertyobject *gs = (propertyobject *)self;
|
||||
PyObject *func, *res;
|
||||
|
||||
if (value == NULL)
|
||||
func = gs->prop_del;
|
||||
else
|
||||
func = gs->prop_set;
|
||||
if (func == NULL) {
|
||||
PyErr_SetString(PyExc_AttributeError,
|
||||
value == NULL ?
|
||||
"can't delete attribute" :
|
||||
"can't set attribute");
|
||||
return -1;
|
||||
}
|
||||
if (value == NULL)
|
||||
res = PyObject_CallFunction(func, "()");
|
||||
else
|
||||
res = PyObject_CallFunction(func, "(O)", value);
|
||||
if (res == NULL)
|
||||
return -1;
|
||||
Py_DECREF(res);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static PyTypeObject static_data_object = {
|
||||
PyObject_HEAD_INIT(0)//&PyType_Type)
|
||||
0,
|
||||
"Boost.Python.class",
|
||||
PyType_Type.tp_basicsize,
|
||||
0,
|
||||
0, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
|
||||
| Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
0, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, //&PyProperty_Type, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
static_data_descr_get, /* tp_descr_get */
|
||||
static_data_descr_set, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
0, // filled in with type_new /* tp_new */
|
||||
0, // filled in with __PyObject_GC_Del /* tp_free */
|
||||
(inquiry)type_is_gc, /* tp_is_gc */
|
||||
};
|
||||
|
||||
namespace objects
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
// This declaration needed due to broken Python 2.2 headers
|
||||
extern DL_IMPORT(PyTypeObject) PyProperty_Type;
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL PyObject* static_data()
|
||||
{
|
||||
if (static_data_object.tp_dict == 0)
|
||||
{
|
||||
static_data_object.ob_type = &PyType_Type;
|
||||
static_data_object.tp_base = &PyProperty_Type;
|
||||
if (PyType_Ready(&static_data_object))
|
||||
return 0;
|
||||
}
|
||||
return upcast<PyObject>(&static_data_object);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
// Ordinarily, descriptors have a certain assymetry: you can use
|
||||
// them to read attributes off the class object they adorn, but
|
||||
// writing the same attribute on the class object always replaces
|
||||
// the descriptor in the class __dict__. In order to properly
|
||||
// represent C++ static data members, we need to allow them to be
|
||||
// written through the class instance. This function of the
|
||||
// metaclass makes it possible.
|
||||
static int
|
||||
class_setattro(PyObject *obj, PyObject *name, PyObject* value)
|
||||
{
|
||||
// Must use "private" Python implementation detail
|
||||
// _PyType_Lookup instead of PyObject_GetAttr because the
|
||||
// latter will always end up calling the descr_get function on
|
||||
// any descriptor it finds; we need the unadulterated
|
||||
// descriptor here.
|
||||
PyObject* a = _PyType_Lookup(downcast<PyTypeObject>(obj), name);
|
||||
|
||||
// a is a borrowed reference or 0
|
||||
|
||||
// If we found a static data descriptor, call it directly to
|
||||
// force it to set the static data member
|
||||
if (a != 0 && PyObject_IsInstance(a, objects::static_data()))
|
||||
return a->ob_type->tp_descr_set(a, obj, value);
|
||||
else
|
||||
return PyType_Type.tp_setattro(obj, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
static PyTypeObject class_metatype_object = {
|
||||
@@ -72,7 +216,7 @@ static PyTypeObject class_metatype_object = {
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
class_setattro, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
|
||||
| Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
@@ -110,6 +254,8 @@ void instance_holder::install(PyObject* self) throw()
|
||||
|
||||
namespace objects
|
||||
{
|
||||
static int (*class_setattro_save)(PyObject *obj, PyObject *name, PyObject* value);
|
||||
|
||||
// Get the metatype object for all extension classes.
|
||||
BOOST_PYTHON_DECL type_handle class_metatype()
|
||||
{
|
||||
@@ -119,6 +265,7 @@ namespace objects
|
||||
class_metatype_object.tp_base = &PyType_Type;
|
||||
if (PyType_Ready(&class_metatype_object))
|
||||
return type_handle();
|
||||
class_setattro_save = class_metatype_object.tp_setattro;
|
||||
}
|
||||
return type_handle(borrowed(&class_metatype_object));
|
||||
}
|
||||
@@ -189,6 +336,7 @@ namespace objects
|
||||
inst->dict = python::incref(dict);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -254,6 +402,7 @@ namespace objects
|
||||
class_type_object.tp_base = &PyBaseObject_Type;
|
||||
if (PyType_Ready(&class_type_object))
|
||||
return type_handle();
|
||||
// class_type_object.tp_setattro = class_setattro;
|
||||
}
|
||||
return type_handle(borrowed(&class_type_object));
|
||||
}
|
||||
@@ -377,12 +526,6 @@ namespace objects
|
||||
this->attr("__instance_size__") = instance_size;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
// This declaration needed due to broken Python 2.2 headers
|
||||
extern DL_IMPORT(PyTypeObject) PyProperty_Type;
|
||||
}
|
||||
|
||||
void class_base::add_property(char const* name, object const& fget)
|
||||
{
|
||||
object property(
|
||||
@@ -401,6 +544,24 @@ namespace objects
|
||||
this->setattr(name, property);
|
||||
}
|
||||
|
||||
void class_base::add_static_property(char const* name, object const& fget)
|
||||
{
|
||||
object property(
|
||||
(python::detail::new_reference)
|
||||
PyObject_CallFunction(static_data(), "O", fget.ptr()));
|
||||
|
||||
this->setattr(name, property);
|
||||
}
|
||||
|
||||
void class_base::add_static_property(char const* name, object const& fget, object const& fset)
|
||||
{
|
||||
object property(
|
||||
(python::detail::new_reference)
|
||||
PyObject_CallFunction(static_data(), "OO", fget.ptr(), fset.ptr()));
|
||||
|
||||
this->setattr(name, property);
|
||||
}
|
||||
|
||||
void class_base::setattr(char const* name, object const& x)
|
||||
{
|
||||
if (PyObject_SetAttrString(this->ptr(), const_cast<char*>(name), x.ptr()) < 0)
|
||||
|
||||
@@ -18,7 +18,11 @@ using namespace boost::python;
|
||||
|
||||
typedef test_class<> X;
|
||||
|
||||
typedef test_class<1> Y;
|
||||
struct Y : test_class<1>
|
||||
{
|
||||
Y(int v) : test_class<1>(v) {}
|
||||
Y& operator=(Y const& rhs) { x = rhs.x; return *this; }
|
||||
};
|
||||
|
||||
double get_fair_value(X const& x) { return x.value(); }
|
||||
|
||||
@@ -29,6 +33,7 @@ struct VarBase
|
||||
|
||||
std::string const name;
|
||||
std::string get_name1() const { return name; }
|
||||
|
||||
};
|
||||
|
||||
struct Var : VarBase
|
||||
@@ -38,8 +43,14 @@ struct Var : VarBase
|
||||
float value;
|
||||
char const* name2;
|
||||
Y y;
|
||||
|
||||
static int static1;
|
||||
static Y static2;
|
||||
};
|
||||
|
||||
int Var::static1 = 0;
|
||||
Y Var::static2(0);
|
||||
|
||||
BOOST_PYTHON_MODULE(data_members_ext)
|
||||
{
|
||||
class_<X>("X", init<int>())
|
||||
@@ -74,6 +85,17 @@ BOOST_PYTHON_MODULE(data_members_ext)
|
||||
.def("get_name2", &Var::get_name2, return_value_policy<return_by_value>())
|
||||
|
||||
.add_property("name3", &Var::get_name1)
|
||||
|
||||
// Test static data members
|
||||
.def_readonly("ro1a", &Var::static1)
|
||||
.def_readonly("ro1b", Var::static1)
|
||||
.def_readwrite("rw1a", &Var::static1)
|
||||
.def_readwrite("rw1b", Var::static1)
|
||||
|
||||
.def_readonly("ro2a", &Var::static2)
|
||||
.def_readonly("ro2b", Var::static2)
|
||||
.def_readwrite("rw2a", &Var::static2)
|
||||
.def_readwrite("rw2b", Var::static2)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,151 @@
|
||||
'''
|
||||
>>> from data_members_ext import *
|
||||
|
||||
---- Test static data members ---
|
||||
|
||||
>>> v = Var('slim shady')
|
||||
|
||||
>>> Var.ro2a.x
|
||||
0
|
||||
>>> Var.ro2b.x
|
||||
0
|
||||
>>> Var.rw2a.x
|
||||
0
|
||||
>>> Var.rw2b.x
|
||||
0
|
||||
>>> v.ro2a.x
|
||||
0
|
||||
>>> v.ro2b.x
|
||||
0
|
||||
>>> v.rw2a.x
|
||||
0
|
||||
>>> v.rw2b.x
|
||||
0
|
||||
>>> Var.rw2a.x = 777
|
||||
>>> Var.ro2a.x
|
||||
777
|
||||
>>> Var.ro2b.x
|
||||
777
|
||||
>>> Var.rw2a.x
|
||||
777
|
||||
>>> Var.rw2b.x
|
||||
777
|
||||
>>> v.ro2a.x
|
||||
777
|
||||
>>> v.ro2b.x
|
||||
777
|
||||
>>> v.rw2a.x
|
||||
777
|
||||
>>> v.rw2b.x
|
||||
777
|
||||
>>> Var.rw2b = Y(888)
|
||||
>>> Var.ro2a.x
|
||||
888
|
||||
>>> Var.ro2b.x
|
||||
888
|
||||
>>> Var.rw2a.x
|
||||
888
|
||||
>>> Var.rw2b.x
|
||||
888
|
||||
>>> v.ro2a.x
|
||||
888
|
||||
>>> v.ro2b.x
|
||||
888
|
||||
>>> v.rw2a.x
|
||||
888
|
||||
>>> v.rw2b.x
|
||||
888
|
||||
>>> v.rw2b.x = 999
|
||||
>>> Var.ro2a.x
|
||||
999
|
||||
>>> Var.ro2b.x
|
||||
999
|
||||
>>> Var.rw2a.x
|
||||
999
|
||||
>>> Var.rw2b.x
|
||||
999
|
||||
>>> v.ro2a.x
|
||||
999
|
||||
>>> v.ro2b.x
|
||||
999
|
||||
>>> v.rw2a.x
|
||||
999
|
||||
>>> v.rw2b.x
|
||||
999
|
||||
|
||||
|
||||
>>> Var.ro1a
|
||||
0
|
||||
>>> Var.ro1b
|
||||
0
|
||||
>>> Var.rw1a
|
||||
0
|
||||
>>> Var.rw1b
|
||||
0
|
||||
>>> v.ro1a
|
||||
0
|
||||
>>> v.ro1b
|
||||
0
|
||||
>>> v.rw1a
|
||||
0
|
||||
>>> v.rw1b
|
||||
0
|
||||
>>> Var.rw1a = 777
|
||||
>>> Var.ro1a
|
||||
777
|
||||
>>> Var.ro1b
|
||||
777
|
||||
>>> Var.rw1a
|
||||
777
|
||||
>>> Var.rw1b
|
||||
777
|
||||
>>> v.ro1a
|
||||
777
|
||||
>>> v.ro1b
|
||||
777
|
||||
>>> v.rw1a
|
||||
777
|
||||
>>> v.rw1b
|
||||
777
|
||||
>>> Var.rw1b = 888
|
||||
>>> Var.ro1a
|
||||
888
|
||||
>>> Var.ro1b
|
||||
888
|
||||
>>> Var.rw1a
|
||||
888
|
||||
>>> Var.rw1b
|
||||
888
|
||||
>>> v.ro1a
|
||||
888
|
||||
>>> v.ro1b
|
||||
888
|
||||
>>> v.rw1a
|
||||
888
|
||||
>>> v.rw1b
|
||||
888
|
||||
>>> v.rw1b = 999
|
||||
>>> Var.ro1a
|
||||
999
|
||||
>>> Var.ro1b
|
||||
999
|
||||
>>> Var.rw1a
|
||||
999
|
||||
>>> Var.rw1b
|
||||
999
|
||||
>>> v.ro1a
|
||||
999
|
||||
>>> v.ro1b
|
||||
999
|
||||
>>> v.rw1a
|
||||
999
|
||||
>>> v.rw1b
|
||||
999
|
||||
|
||||
|
||||
|
||||
-----------------
|
||||
|
||||
>>> x = X(42)
|
||||
>>> x.x
|
||||
42
|
||||
@@ -39,6 +184,7 @@
|
||||
>>> v.name3
|
||||
'pi'
|
||||
|
||||
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
|
||||
Reference in New Issue
Block a user