Add member functions to a Boost Python class after

2019-07-27 09:41发布

问题:

In Boost Python, you can expose a C++ class to Python like this:

object obj = class_<MyClass>("MyClass")
    .def("SomeFunc", &MyClass::SomeFunc)
    ;

Let's say MyClass also has a function SomeOtherFunc. Is there a way to expose SomeOtherFunc to Python later on in the BOOST_PYTHON_MODULE code? I tried using the returned object, but it has no property def. I also tried instantiating the exposing of MyClass again, but that just overwrote the first one. Essentially I'm looking for something like this:

obj.def("SomeOtherFunc", &MyClass::SomeOtherFunc)

The larger problem that I'm trying to solve is that I have a number of classes that inherit from a templated base class, and I'm trying to find a way to expose them to Python in a clean way. So far, I've made a template function that takes in the class and its template parameter and constructs the necessary class_ calls, but I might want to modify the definition of the exposed class later, so I'm not sure how to do that.

Bonus points if someone can explain exactly what "def" is doing and why I don't need commas in between defs.

回答1:

obj doesn't have a member function named def, but class_ does. class_ inherits from object, which is why that assignment works, but you don't have to do that. The following works fine:

auto obj = class_<MyClass>("MyClass")
    .def("SomeFunc", &MyClass::SomeFunc)
;

// now obj is an instance of py::class_<MyClass> instead of py::object
obj.def("SomeOtherFunc", &MyClass::SomeOtherFunc);

The fact that you never name the class_ instance may distract from the fact that this is a simple constructor. You could have also written the above as:

class_<MyClass> obj("MyClass");
obj.def("SomeFunc", &MyClass::SomeFunc);
obj.def("SomeOtherFunc", &MyClass::SomeOtherFunc);

You don't have to define everything in one go.

Bonus points if someone can explain exactly what def is doing and why I don't need commas in between defs.

def is a member function on the class template class_. It has a bunch of overloads, all of which returns a reference to self:

template <class Init>         class_& def(Init );
template <class F>            class_& def(char const*, Fn );
template <class Fn, class A1> class_& def(char const*, Fn, A1 );
// etc.

That's why you can chain them. Each call independently sets up the internal machinery to expose that function to python and just returns *this. I don't know what you would need commas for.



标签: python c++ boost