Boost logo

Boost :

From: scott snyder (snyder_at_[hidden])
Date: 2001-12-02 19:55:26


hi -

Here are some patches to boost::python (against boost 1.25.1)
to better implement static class data members.

With these changes, the following works:

class T
{
public:
  static int x;
};

...

  this_class.def_read_write (&T::x, "x");

sss

--- boost/python/detail/extension_class.hpp-orig2 Sat Dec 1 01:10:16 2001
+++ boost/python/detail/extension_class.hpp Sat Dec 1 01:17:32 2001
@@ -532,6 +532,15 @@
         this->add_getter_method(new getter_function<T, MemberType>(pm), name);
     }
     
+ // Provide a function which implements x.<name>, reading from the given
+ // static member (pm) of the T class
+ template <class MemberType>
+ inline void def_getter(MemberType *pm, const char* name)
+ {
+ this->add_getter_method(new static_getter_function<MemberType>(pm),
+ name);
+ }
+
     // Provide a function which implements assignment to x.<name>, writing to
     // the given member (pm) of the T obj
     template <class MemberType>
@@ -540,6 +549,15 @@
         this->add_setter_method(new setter_function<T, MemberType>(pm), name);
     }
     
+ // Provide a function which implements assignment to x.<name>, writing to
+ // the given static member (pm) of the T class
+ template <class MemberType>
+ inline void def_setter(MemberType *pm, const char* name)
+ {
+ this->add_setter_method(new static_setter_function<MemberType>(pm),
+ name);
+ }
+
     // Expose the given member (pm) of the T obj as a read-only attribute
     template <class MemberType>
     inline void def_readonly(MemberType T::*pm, const char* name)
@@ -547,6 +565,15 @@
         this->add_setter_method(new read_only_setattr_function(name), name);
         this->def_getter(pm, name);
     }
+
+ // Expose the given static member (pm) of the T class
+ // as a read-only attribute
+ template <class MemberType>
+ inline void def_readonly(MemberType *pm, const char* name)
+ {
+ this->add_setter_method(new read_only_setattr_function(name), name);
+ this->def_getter(pm, name);
+ }
     
     // Expose the given member (pm) of the T obj as a read/write attribute
     template <class MemberType>
@@ -554,6 +581,15 @@
     {
         this->def_getter(pm, name);
         this->def_setter(pm, name);
+ }
+
+ // Expose the given static member (pm) of the T class
+ // as a read/write attribute
+ template <class MemberType>
+ inline void def_read_write(MemberType *pm, const char* name)
+ {
+ this->def_getter(pm, name);
+ this->def_setter(pm, name);
     }
     
     // define the standard coercion needed for operator overloading
--- boost/python/detail/functions.hpp-orig Fri Nov 30 19:14:24 2001
+++ boost/python/detail/functions.hpp Sat Dec 1 02:25:03 2001
@@ -288,6 +288,43 @@
     return none();
 }
 
+// Same, for static members/variables.
+template <class MemberType>
+class static_getter_function : public function
+{
+ public:
+ typedef MemberType* pointer_to_member;
+
+ static_getter_function(pointer_to_member pm)
+ : m_pm(pm) {}
+
+ private:
+ PyObject* do_call(PyObject* args, PyObject* keywords) const;
+
+ const char* description() const
+ { return typeid(MemberType (*)()).name(); }
+ private:
+ pointer_to_member m_pm;
+};
+
+template <class MemberType>
+class static_setter_function : public function
+{
+ public:
+ typedef MemberType* pointer_to_member;
+
+ static_setter_function(pointer_to_member pm)
+ : m_pm(pm) {}
+
+ private:
+ PyObject* do_call(PyObject* args, PyObject* keywords) const;
+
+ const char* description() const
+ { return typeid(void (*)(const MemberType&)).name(); }
+ private:
+ pointer_to_member m_pm;
+};
+
 template <class T, class R, class V, class D>
 PyObject* virtual_function<T,R,V,D>::do_call(PyObject* args, PyObject* keywords) const
 {
@@ -306,6 +343,30 @@
     return caller<R>::call(m_default_implementation, args, keywords);
 }
     
+template <class MemberType>
+PyObject* static_getter_function<MemberType>::do_call(
+ PyObject* args, PyObject* /* keywords */) const
+{
+ if (!PyArg_ParseTuple(args, const_cast<char*>("")))
+ return 0;
+
+ return to_python(*m_pm);
+}
+
+template <class MemberType>
+PyObject* static_setter_function<MemberType>::do_call(
+ PyObject* args, PyObject* /* keywords */) const
+{
+ PyObject* value;
+ if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &value))
+ return 0;
+
+ typedef typename boost::call_traits<MemberType>::const_reference extract_type;
+ *m_pm = from_python(value, type<extract_type>());
+
+ return none();
+}
+
 }}} // namespace boost::python::detail
 
 #endif // FUNCTIONS_DWA051400_H_
--- libs/python/src/classes.cpp-orig2 Sat Dec 1 02:04:36 2001
+++ libs/python/src/classes.cpp Sat Dec 1 02:36:47 2001
@@ -213,6 +213,14 @@
       if (local_attribute.get())
           return local_attribute.release();
 
+ // Check for __getattr__name__
+ PyErr_Clear ();
+ const string specific_getattr_name(detail::getattr_string() + name + "__");
+ ref getattr_method = m_name_space.get_item (specific_getattr_name.reference());
+ if (getattr_method.get() != 0) {
+ return PyEval_CallFunction (getattr_method.get(), "()");
+ }
+
       // In case there are no bases...
       PyErr_SetString(PyExc_AttributeError, name);
 
@@ -275,6 +283,13 @@
           throw error_already_set();
       }
       
+ const string specific_method_name(detail::setattr_string() + name + "__");
+ ref setattr_method = m_name_space.get_item (specific_method_name.reference());
+ if (setattr_method.get() != 0) {
+ ref res (PyEval_CallFunction (setattr_method.get(), "(O)", value));
+ return res.get() == 0;
+ }
+
       if (PyCallable_Check(value))
           detail::enable_named_method(this, name);
       


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk