I just wanted to thank http://mail.python.org/pipermail/cplusplus-sig/2007-July/012293.html
I've extended what he wrote.. I needed late binding for c++ to python objects. Hope this is useful for someone else. Maybe there was some other way I was supposed to do this, but I couldn't find it. Um.. And yes this code was just cobbled together.. BasePtr is a horrible name I know. :-) #define BOOST_PYTHON_STATIC_LIB #include <boost/python.hpp> #include <boost/detail/lightweight_test.hpp> #include <boost/python/module.hpp> #include <iostream> #include <map> namespace python = boost::python; class Base; //------------------------------------------------------ #define IMPLEMENT_PYTHON_ACCESSOR_H \ public: \ static void setClass (boost::python::object _clazz) { clazz = _clazz; } \ static boost::python::object getClass() { return clazz; } \ virtual void reflectBind (boost::python::object object) \ { \ ::bind(this, object); \ } \ private: \ static boost::python::object clazz; \ #define IMPLEMENT_PYTHON_ACCESSOR_CPP(x) \ boost::python::object x::clazz; //------------------------------------------------------ template<typename T> void bind (T *self, boost::python::object object) { // Insert new S object pointer into python object typedef boost::python::objects::pointer_holder<T *, T> holder; typedef boost::python::objects::instance<holder> instance_t; void* memory = holder::allocate( object.ptr(), offsetof(instance_t, storage), sizeof(holder) ); try { (new (memory) holder(self))->install(object.ptr()); } catch(...) { holder::deallocate(object.ptr(), memory); throw; } } //------------------------------------------------------ class BasePtr { public: BasePtr() { std::cout << this; }; virtual ~BasePtr () { }; virtual void reflectBind (boost::python::object pyobject) { } void bind (boost::python::object pyobject) { reflectBind (pyobject); this->object = pyobject; } python::object object; python::object getObject () const { return object; } void doBind (python::object o) { bind( o); } static python::object nowhere (python::object); } ; //---------------------------------------------------- class Base : public BasePtr { IMPLEMENT_PYTHON_ACCESSOR_H public: virtual ~Base() { }; Base () { } virtual std::string hello() { std::cout << this; return "Base says hello"; } virtual Base *myself () { return this; } }; IMPLEMENT_PYTHON_ACCESSOR_CPP (Base); class Inherited : public Base { IMPLEMENT_PYTHON_ACCESSOR_H public: Inherited () { } virtual ~Inherited () { } std::string hello() { std::cout << this; return "Inherited says hello"; } } ; IMPLEMENT_PYTHON_ACCESSOR_CPP (Inherited); /* Not needed after all template<typename T> struct BaseToReference { static PyObject* convert(const T &x) { if (&x == 0) return python::incref(python::object().ptr()); return python::incref(x.getObject().ptr()); } }; */ python::object BasePtr::nowhere (python::object pyobject) { return python::object(); } //--------------------------------------------------- BOOST_PYTHON_MODULE(embedded_hello) { Base::setClass( python::class_<Base, boost::noncopyable> ("Base", python::no_init) .def("__init__", &BasePtr::nowhere) .def ("hello", &Base::hello, python::return_value_policy<python::return_by_value>()) .def ("myself", &Base::myself, python::return_value_policy<python::reference_existing_object>()) ); Inherited::setClass ( python::class_<Inherited, python::bases<Base>, boost::noncopyable> ("Inherited", python::no_init) .def("__init__", &BasePtr::nowhere) .def ("hello", &Inherited::hello, python::return_value_policy<python::return_by_value>()) ); // not needed after all // python::to_python_converter<Base, BaseToReference<Base> >(); } //--------------------------------------------------- int main(int argc, char **argv) { // Initialize the interpreter Py_Initialize(); bool error_expected = false; if (PyImport_AppendInittab("embedded_hello", initembedded_hello) == -1) throw std::runtime_error("Failed to add embedded_hello to the interpreter's " "builtin modules"); PyObject *z2 = PyImport_ImportModule ("embedded_hello"); python::object module (python::handle<>(PyImport_ImportModule ("embedded_hello"))); python::object dict = module.attr("__dict__"); // Retrieve the main module python::object main = python::import("__main__"); // Retrieve the main module's namespace python::object global(main.attr("__dict__")); python::object result1 = python::exec( "from embedded_hello import * \n" "class PythonDerived(Base): \n" " def __init__(self): \n" " Base.__init__(self); \n" "\n" " def hello(self): \n" " print 'hello from python' \n" " print Base.hello(self) \n" " return 'Hello from Python!' \n" "\n" " def test(self): \n" " print 'test1 says ' \n" " print self.myself().hello()\n" , global, global); Base b; b.doBind(global["PythonDerived"]()); python::object o(b.object); ; python::object r = o.attr("hello")(); o.attr("test")(); python::object result2 = python::exec( "from embedded_hello import * \n" "class PythonDerived2(Inherited): \n" " def __init__(self): \n" " Inherited.__init__(self); \n" "\n" " def hello(self): \n" " print 'hello from python' \n" " print Inherited.hello(self) \n" " return 'Hello from Python!' \n" "\n" " def test(self): \n" " print 'test2 says ' \n" " print self.myself().hello()\n" , global, global); Inherited c; c.doBind(global["PythonDerived2"]()); python::object oc(c.object); ; python::object rc = oc.attr("hello")(); oc.attr("test")(); std::cout << "success!" << std::endl; } _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig