Reputation: 11
first of all, thanks for this great project!
I have the following situation: I'm developing a C++ library which uses drake
as a dependency. Specifically I have a custom System, inheriting from LeafSystem<T>
:
// my_system.h
#include <drake/systems/framework/leaf_system.h>
template <typename T>
class MySystem : public drake::systems::LeafSystem<T> {
public:
MySystem() {}
};
I want to expose this system also via a Python API, also using pybind11 like drake is doing, i.e.:
// my_module.cpp
#include "my_system.h"
#include <drake/systems/framework/leaf_system.h>
#include <pybind11/pybind11.h>
namespace py = pybind11;
PYBIND11_MODULE(my_module, m) {
py::module::import("pydrake.systems.framework");
py::class_<MySystem<double>, drake::systems::LeafSystem<double>>(m, "MySystem").def(py::init<>());
}
This compiles with CMake, life is good. But when I try to import MySystem
in python, the base class cannot be resolved:
>>> import my_module
Traceback (most recent call last):
Cell In [2], line 1
import my_module
ImportError: generic_type: type "MySystem" referenced unknown base type "drake::systems::LeafSystem<double>"
I suspect it has something to do with the way drake generates the actual name of the binding, but this is all way beyond my head: https://github.com/RobotLocomotion/drake/blob/72794d7818ef51629ed97faf6cd325004f49eb9a/bindings/pydrake/common/cpp_template_pybind.h#L90-L93
How can I create python bindings for my class which inherits from drake::system::framework::LeafSystem
(or any other system, really)?
Thanks for your help!
The only relevant information I could find on pybind11
is from the officle docs about inheritance, which don't apply in my case, since the bindings of the base have already been written.
I tried to simulate the situation by compiling a libfoo.so
which exports one base class Foo
and its bindings. If MySystem
inherits from Foo
I can get the python binding to work just fine:
// Simulated foo library and its bindings
class Foo {};
#include "foo.h"
#include <pybind11/pybind11.h>
namespace py = pybind11;
PYBIND11_MODULE(foo, m) {
m.doc() = "hello, foo";
py::class_<Foo>(m, "Foo").def(py::init<>());
}
In another lib, this now works:
class MySystem : Foo {};
PYBIND11_MODULE(my_module, m) {
py::class_<MySystem, Foo>(m, "MySystem").def(py::init<>());
}
Upvotes: 1
Views: 181
Reputation: 2464
Does it fix it if you add py::module::import("pydrake.systems.framework");
to your PYBIND11_MODULE
before trying to define your class?
For any C++ classes used by a pybind11 binding that are from other modules, you need to py::import
that module before you can inherit from it (or use it as an argument, or etc).
Upvotes: 1