Reputation: 79021
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?
Upvotes: 1
Views: 1352
Reputation: 991
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.
Upvotes: 2