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
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig