-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Subclass python class in C++ #1193
Comments
I tried to do the same (see #1170) and failed. Good luck. |
What sort of things do you need to do with your C++-extended Python class?
You could take this route, but automate either with monkey patching or codegen (with Python, I'd just go with monkey patching). You could make some function called You could potentially do this all in Python, and not need to worry anything about anything C++ / pybind-specific. For example, I'm prototyping a way to expose template parameters to Python for functions, classes, methods, etc. using this kind of mechanism: |
pybind11 doesn't allow this, and it's unlikely to change in the future. py::object parent_class = py::module::import("package").attr("ParentClass");
py::object parent_metaclass = py::reinterpret_borrow<py::object>((PyObject *) &PyType_Type);
py::dict attributes;
attributes["test"] = py::cpp_function(
[](py::object self, py::object x) {
py::print(x);
},
py::arg("x"),
py::is_method(py::none())
);
m.attr("MyClass") = parent_metaclass("MyClass", py::make_tuple(parent_class), attributes); |
@TkTech suggested I'd add my own hack here (discussed on Gitter), for future reference: You can, if you really want, do the following horrible thing, given some binding.attr("__bases__") = py::make_tuple(typeHandle) + binding.attr("__bases__");
That being said/warned: have fun. |
Unfortunately, @YannickJadoul approach does not work when bases have incompatible base types. For example, you cannot use this to mixin |
That's a pity, but not unexpected, maybe. At any rate, the other suggested solution should still work? |
@YannickJadoul your suggestion worked great for my (rather simple) use-case, thanks! |
I had occasion to adapt this approach recently and thought I would share: https://github.com/llvm/circt/blob/faa0e1827a116292156ff32260a195b1caf3cdce/lib/Bindings/Python/MLIRPybindAdaptors.h#L220 And where it is used: https://github.com/llvm/circt/blob/faa0e1827a116292156ff32260a195b1caf3cdce/lib/Bindings/Python/ESIModule.cpp#L113 I didn't spend a great deal of time shaving all of the edges off of it, but it feels like something that could be made relatively general and usable. |
If you Google "pybind11 subclass" you will find a couple of threads on how to solve the problem, none of which worked in this scenario. The issue on the pybind github about subclasses (below) cites a way to subclass an existing binding that feels as robust as creating a class on the fly using type("MyClass", bases, attrs) -> pybind/pybind11#1193 Another issue recommends using py:base, which has been deprecated. -> pybind/pybind11#17 ...also it didn't work. It seems to me that because we are defining each class as an .inl rather than a .hpp or .cpp file, they are not aware of each other. To remedy this, I've included the MDGModifier binding in the MDagModifier file, with an pre-processor to prevent duplicate entries. Otherwise, the base class would be omitted in the main.cpp. I think this solution will work well when we get to other classes with many subclasses, like the whole MFn* tree.
…ybind#1193 does not allow for passing kwargs.
The method described in #1193 (comment) does not seem to allow for passing kwargs: #5406 Is there another way to accomplish that? |
I'm trying to create a C++ class that inherits from a python class. However, it does not work. Here is a short example of what i'm trying to do:
foo.py:
bar.cpp
When importing the bar module, I get multiple errors. First of all, I get a failed assertion in https://github.com/pybind/pybind11/blob/master/include/pybind11/detail/class.h#L604. This can be solved by adding the
py::dynamic_attr()
tag to the class definition. However, then I get a segmentation fault in https://github.com/pybind/pybind11/blob/master/include/pybind11/pybind11.h#L916.So I wonder if this could be supported directly. Of course I could just write my c++ class, and then make a thin wrapper in python inheriting from the python class, but that is just a lot more tedious.
The text was updated successfully, but these errors were encountered: