I have a C++ that takes an object of the abstract DomainBase class,
void
generate(const std::shared_ptr<foo::DomainBase> & domain)
Since it's using a shared_ptr here, I specified that in the pybind11 wrapper code for DomainBase like
py::class_<DomainBase, std::shared_ptr<DomainBase>>(m, "DomainBase");
I can now call generate for all classes derived in C++ from DomainBase, e.g.,
import foo
b = foo.Ball([0.0, 0.0, 0.0], 1.0)
foo.generate(b)
Now, I would like to extend this by deriving a class _within Python_, e.g.,
class Hyperboloid(foo.DomainBase):
def __init__(self):
return
def eval(self, x):
if self.z0 < x[2] and x[2] < self.z1:
r2 = x[0]**2 + x[1]**2
return r2 - (x[2]**2 + 0.5)**2
else:
return 1.0
h = Hyperboloid()
foo.generate(h)
This fails with the
RuntimeError: Unable to cast from non-held to held instance (T& to Holder<T>) (compile in debug mode for type information)
I can only guess that this has to do with the usage of shared_ptrs, and that, just like DomainBase and Ball, I would have to declare Hyperboloid a "shared_ptr" class.
Any hints?
def __init__(self):
return
This is missing the superclass initializer and so the C++ instance doesn't get initialized:
def __init__(self):
foo.DomainBase.__init__(self)
# or `super(Hyperboloid, self).__init__()`, or in Python 3: `super().__init__()`
This is giving my some trouble. Some members of base class DomainBase are purely virtual, e.g.,
virtual double eval(const std::array<double, 3> & x) const = 0;
so adding an init to the pybind11 interface
py::class_<DomainBase, std::shared_ptr<DomainBase>>(m, "DomainBase")
.def(py::init<>());
gives me the compile error
invalid new-expression of abstract class type ‘foo::DomainBase’
I guess as a workaround I could replace the purely virtual members by members that just throw an exception. Unless there is another way...
For virtual methods you'll need to use a trampoline class that implements the virtual methods and forwards them to Python. See the docs
I'll close this, with a recommendation to use the gitter channel for how-do-I-do-x type questions (to keep issue reports for genuine bugs/issues rather than help questions).
Most helpful comment
This is missing the superclass initializer and so the C++ instance doesn't get initialized: