Reputation: 642
I use pybind11 as a wrapper of my C++ code into a python library.
It happens that there are arguments that I can't provide or sometimes I want to do a conversion/initialization that I know in the C++ side. It could be because the class is not known in python, for instance. How could that be done? The only "solution" I see so far would be to create an inherited proxy class in C++.
Example: I want to define/bind a python class A:
class A:
def __init__(self, B b):
...
With a C++ equivalent class:
class A {
A(C c, D d);
}
Is there some kind of lambda or an equivalent that I could create for the pybind11::init<>?
Upvotes: 9
Views: 7741
Reputation: 839
pybind11 lets you bind factory functions as init methods. So you would have to provide a function in c++ that took a B and return an A and then you could bind that as an init method for A.
An example from the pybind11 docs
class Example {
private:
Example(int); // private constructor
public:
// Factory function:
static Example create(int a) { return Example(a); }
};
py::class_<Example>(m, "Example")
.def(py::init(&Example::create));
You should be able to bind in a free function as well (not just a static function), if you do not want to (or can't) change class A in c++.
So it could look something like this (changed to return a unique_ptr, which pybind can just take ownership of vs a raw instance. But either should work)
std::unique_ptr<A> createA(const B& arg)
{
// returns an instance of A that you made using B
}
py::class_<A>(m, "A")
.def(py::init(&createA));
You obviously then have to also provide a binding for B in python.
Docs are here and include even more examples, including how to do an init lambda as well: https://pybind11.readthedocs.io/en/stable/advanced/classes.html#custom-constructors
Upvotes: 10