0

I have python embedded in my application and I want to send a python function a raw pointer to an object I have in my C++ code.
The only way I found how to do this is to wrap the pointer with an auto_ptr or a shared_ptr but I prefer not to do that since I don't want the python code to have any chance of holding a reference to the object in my code.

Is this possible with boost::python?

shoosh
  • 76,898
  • 55
  • 205
  • 325
  • Looks like http://stackoverflow.com/a/5056462/138772 has your solution. "Pass the object pointer via boost::python::ptr to python. This will prevent the python interpreter from making a copy". – JAB Jun 26 '12 at 18:50
  • @JAB Nice! Write it as an answer and I'll accept it. – shoosh Jun 27 '12 at 07:24
  • Actually, it seems I didn't look into it enough/didn't read what I copied and pasted properly. It looks like using `boost::python::ptr` will actually make the possibility of dangling references _more_ likely, as according to http://www.boost.org/doc/libs/1_49_0/libs/python/doc/v2/ptr.html, "Normally, when passing pointers to Python callbacks, the pointee is copied to ensure that the Python object never holds a dangling reference." – JAB Jun 27 '12 at 14:54

1 Answers1

0

If you have raw pointer to some C++ object mapped into Python then you can make another Python object around original pointer using adapter in such way:

template<typename PtrT>
struct PtrAdapter {
    auto& get(PtrT ptr)  { return *ptr; }
};

Then make it's Python mapped type and allow implicit conversion:

class_<Cluster<LinksT>*, noncopyable>(typpedName<LinksT>("ClusterPtr", true, true)
, "Raw hierarchy cluster pointer\n")
    .def("__call__", &PtrAdapter<Cluster<LinksT>*>::get,
        return_internal_reference<>(),
        "referenced cluster")
    ;
register_ptr_to_python<Cluster<LinksT>*>();

Note that referenced type (in this case Cluster<LinksT>) also must be mapped to the appropriate Python object.
Then for such C++ code:

Cluster<LinksT>* cl = clusters.head();
process(cl);
Id cid = cl->id();

You can use similar Python code:

cl = clusters.head()
process(cl)
cid = cl.id()

But if you don't need some special processing of pointer to C++ object then it's obviously better to use boost::python::ptr.
Also you should consider alternatives mentioned here: boost::python: howto call a function that expects a pointer?

Community
  • 1
  • 1
luart
  • 1,383
  • 1
  • 18
  • 25