[C++-sig] Python __init__ that copies internal reference, boost.python
Branan Purvine-Riley
branan at gmail.com
Tue Aug 17 01:21:17 CEST 2010
On Monday 16 August 2010 14:49:04 Jim Bosch wrote:
> On 08/16/2010 02:33 PM, Branan Purvine-Riley wrote:
> > I'm working on replacing hand-rolled python bindings with boost.python.
> >
> > Unfortunately, I've hit a bit of a snag at a particular construct:
> > a = someFunction(...) # returns an instance of myClass
> > b = myClass(a)
> >
> > In the current bindings, this creates a new python object that references
> > the same internal C++ object. It's effectively no-op, and I have no idea
> > why it was written that way in the first place, but I have to maintain
> > API compatibility.
> >
> > That being the case, how do I implement this in boost.python? I
> > considered replacing __init__, but it seems if I implement that as a
> > standalone function rather than a constructor, boost has already created
> > a new C++ instance for me, so that's too late. I'm not really sure what
> > else to try.
>
> You'll want to use the make_constructor function; this takes a C++
> function returning a C++ smart pointer and creates a Python __init__
> overload.
>
> I *think* this should work (I haven't tested it):
>
> ----------------------------------------------
>
> boost::shared_ptr<MyClass> construct(boost::python::object const & arg) {
> return boost::python::extract< boost::shared_ptr<MyClass> >(arg);
> }
>
> BOOST_PYTHON_MODULE(example) {
> boost::python::class_<MyClass>("MyClass")
> .def("__init__", boost::python::make_constructor(&construct))
> ;
> boost::python::register_ptr_to_python<
> boost::shared_ptr<MyClass>
>
> >();
>
> }
>
That's definitely on the right track. Not quite right because of some of the
oddities of what I'm working with here. It's a game engine, and none of the
pointers are stored in a smart pointer container of any kind. Unfortunately
make_constructor will convert a raw ptr to an std::auto_ptr, which deletes the
object somewhere in boost code.
What I ended up with is the following:
template<typename T>
struct dummy_ptr {
dummy_ptr(T* p) : ptr(p) {}
T* operator->() { return ptr; }
T* ptr;
typedef T element_type;
};
template<typename T>
T* get_pointer(const dummy_ptr<T>& dummy) {
return dummy.ptr;
}
template<typename T>
dummy_ptr<T> noop_constructor(T* arg) {
return dummy_ptr<T>(arg);
}
BOOST_PYTHON_MODULE(example) {
boost::python::class_<MyClass>("MyClass")
.def("__init__",boost::python::make_constructor(&noop_constructor<MyClass>));
boost::python::register_ptr_to_python<dummy_ptr<MyClass> >();
}
More information about the Cplusplus-sig
mailing list