1

I have python embedded in a C++ application. The C++ calls python and passes it as an argument a C++ object. that object has some virtual functions and can be a base class for some derived class. How do I make boost::python understand that it's a virtual function?

consider the following:
in C++:

class Base {
public:
  virtual void func();
}

class Derived {
public:
  virtual void func();
}

BOOST_PYTHON_MODULE(module_api) {
  class_<Base>("Base")
    .def("func", &Base::func);  // ?? what should I put here?
}

int main() {
  //... initialization
  Derived derived;
  main_namespace["pyentry"](&derived);
}

in python:

def pyentry(baseref):
  baseref.func()    # here I want Derived::func() to be called

What am I doing wrong here?

4
  • 3
    You could always put a non-virtual forwarding function: void Base::doFunc() { this->func(); }, .def("func", &Base::doFunc); Commented May 10, 2012 at 17:41
  • I hoped to avoid this overhead... Isn't that what boost::python is supposed to be all about? avoiding overhead...? Commented May 10, 2012 at 17:52
  • you need to wrap up base - boost.org/doc/libs/1_49_0/libs/python/doc/v2/wrapper.html Commented May 11, 2012 at 16:34
  • @barak can you be more specific? I tried this in various forms and couldn't get it to work. I don't want to "override the method in python" I just want to call a virtual polymorphically. Commented May 11, 2012 at 19:10

1 Answer 1

2

The problem here is that Boost.Python is deep-copying your derived-class object and slicing it into a base object when it converts it to Python; there's no need to tell Boost.Python about a function being virtual at all unless you need to override it in Python (and it sounds like you don't).

It's doing that copy to be safe: it's making certain that the object Python is given won't be deleted by C++ while Python still has a reference to it. And it's slicing it to Base - I think - because it doesn't know anything about Derived.

I can think of two ways to fix this:

  • Provide a trivial wrapper for Derived. Boost.Python will still copy it when converting it to Python, but it won't slice it into a Base anymore when it does so.

  • Register a shared_ptr conversion for Base (via register_ptr_to_python< boost::shared_ptr<Base> >()), create your Derived instance in a shared_ptr, and pass that as the argument to your Python function. Now Boost.Python knows the C++ object can't get deleted while the Python object exists, because the Python wrapper holds a shared_ptr reference to it.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.