On 10/11/2010 10:49 AM, Marek Denis wrote:
On 11.10.2010 00:42, Jim Bosch wrote:

Essentially, what you need to do is pass a Python object to call_method
(boost::python::object or PyObject *) that already contains your C++
object. In order to get one, you need need to tell Boost.Python to
construct A and B with what it calls a "back reference". Your C++
constructors will be given a PyObject* by boost.python, pointing to the
Python objects the C++ object will be wrapped in, and you can then store
those as data members and pass the PyObject * to call_method. You can
find more information in the Boost.Python reference docs on class_,
especially the "HeldType Semantics" section.

I did checked the docs, but I think I don't get how should it be done in
my case. What they talk about (as well as in the provided example)
They let the user to create Python classes derived from C++ classes and
launchind virtual Python function. Would ou mind providing a sample
piece of code how should it be done to wrap my C++ object into PyObject*
? Thanks in advance.



I think this is something like what you want to do:

-----------------------------------------

namespace bp = boost::python

class A {
public:

    std::string getData() { return _data; }

    void setCallback(bp::object const & callback) {
        _callback = callback;
    }

    bp::object invokeCallback() {
         return _callback(getSelf());
    }

    virtual PyObject * getSelf() const = 0;

    virtual ~A() {}

    explicit A(std::string const & data) : _data(data) {}

private:
    std::string _data;
    bp::object _callback;
};

class B : public A {
public:
    explicit B(std::string const & data) : A(data) {}
};

class PyA : public A {
public:

    PyA(PyObject * self, std::string const & data) :
        A(data), _self(self) {}

    virtual PyObject * getSelf() const { return _self; }

private:
    PyObject * _self;
};

class PyB : public B {
public:

    PyB(PyObject * self, std::string const & data) :
        B(data), _self(self) {}

    virtual PyObject * getSelf() const { return _self; }

private:
    PyObject * _self;
};

BOOST_PYTHON_MODULE(example) {
    bp::class_<A,PyA>("A", bp::init<std::string>(bp::arg("data")))
        .add_property("data", &A::getData)
        .def("setCallback", &A::setCallback)
        .def("invokeCallback", &A::invokeCallback)
    bp::class_<B,bp::bases<A>,PyB>(
        "B",
         bp::init<std::string>(bp::arg("data"))
    );
}

-----------------------------------------

A couple of notes:

- I have not tested this. Likely there are some typos, and possibly even a bit of forgotten syntax - hopefully it's easy to correct.

- Note that there's no need to re-wrap the methods that B inherits from A, but you do have create both PyA and PyB if you want both A and B to be instantiable from Python (after all, getSelf() is pure virtual).

- If you have a C++ function that returns an A or B instance by reference or pointer, this code will still work. Of course, such an object will have to find some other way to implement getSelf() - only objects instantiated in Python will actually be PyA or PyB instances.

- I didn't actually use call_method anywhere, because bp::object has an overloaded operator() that does what you need (and using object here is better than PyObject because it handles the reference counting; you don't use it for _self because we don't want reference counting there).

- This is a little non-standard because the base classes A and B are Python-aware and are pure virtual - but that makes sense, because your pattern requires that all C++ objects have a back-reference to their Python selves.

- I think there's a way to do this that merges each class with it's Python counterpart (i.e., it tells Boost.Python that A has a constructor that takes the special "self" argument), and it has something to do with specializing a template traits class. But I haven't ever done it, and I don't want to lead you astray.


HTH!

Jim
_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig

Reply via email to