-
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
How to let C++ handle python instances of pybind11 derived types #1902
Comments
You are right, you need to keep (option 1) You can archive it by storing Note: in this approach you will have two Note: you need to make
class CppClass {
public:
CppClass() = default;
virtual void method();
virtual ~CppClass(); // must be virtual!
}; Corresponding changes to /**
* Implements CppClass interface by calling stored py::object.
* Stored py::object extends python object's lifetime.
*/
class PyClassWrapper : public CppClass {
public:
PyClassWrapper(py::object pyClass): m_pyClass(std::move(pyClass)){}
virtual ~PyClassWrapper() = default;
virtual void method(){
m_pyClass.attr("method")();
}
private:
py::object m_pyClass;
};
CppClass* user_defined_function(bool incref) {
py::module module = py::module::import("module");
py::object obj = module.attr("PyClass")();
if (incref) { obj.inc_ref(); }
log("end of user_defined_function");
return new PyClassWrapper(obj); // implicit cast to CppClass*
} The output of main:
(option 2) You can keep table of The first method is simpler to implement correctly, but second one should be more efficient on frequent |
@sizmailov Thank your very much for your detailed answer. I am taking some time to think about the solutions you suggest. I'll be coming back soon. |
@sizmailov I am going for the simple approach of incrementing So far, it's working. Thank you again for the detailed answer. Feel free to close the issue. |
@mmodenesi I have no permissions to close issues. You can close it yourself (as issue author). |
Issue description
My use case is as follows:
Main project written in C++ lets users extend the codebase by subclassing a virtual
CppClass
and providing custom implementation of a virtualmethod
. After registering auser_defined_factory_function
, the application starts creating objects using a pointer to the polymorphicCppClass
type, calling theirmethod
and finally deleting those objects in a way that is completely transparent to users. The whole point of the application is to load the user implementation ofCppClass
derived class.I want to use pybind11 to allow users to subclass
CppClass
and override thismethod
in python.Supose the intepreter is initialized and finalized properly.
Supose the user factory function takes care of finding the python module and creating instances of the Python class deriving from
CppClass
. Then casts thepy::object
and reuturns aCppClass
pointer.The problem that I find is that the python objects are deleted as soon as the factory function returns. I need C++ to take ownership of the object. I repeat: the application takes care of deleting those objects when time comes.
I've read the documentation thoroughly. I've investigated all the questions tagged with
pybind11
on SO. I've searched through the issues and I know this overlaps with:Why do I add another issue, then?
I've explored the solutions proposed on other issues and couldn't fully understand them or tweak them to meet my needs. I am more of a python guy than a C++ guy, I'm trying to improve, though 😃 . In such vein, I think it would be useful to add a section to the documentation exploring the posibilities of using python objects on C++ in more involved ways, and explaining python vs. C++ objects lifecycle.
I think my issue adds value by providing a clear description of the use case as well as a complete example, exploring several posibilities.
Reproducible example code
Working example, just
make
and then./program
.This is what I am pursuing:
This is what I get:
If I manually inc_ref the underlying python object:
More possibilities explored in the full example. The main idea, always, is to manually fiddle with
ref_count
. Is this too hacky?The text was updated successfully, but these errors were encountered: