-
I have a class to which I need to write a function in pybind11 to add dynamic methods. These methods expose low-level methods that are particular to the type contained within itself. In normal Python, we could do like so: https://stackoverflow.com/a/65571141/1360263 But I haven't found a way to do this in pybind11. My desired approach looks something like this: double vdW_get_a(py::object& o){
return std::get<vdWEOS1>(o.cast<const teqp::cppinterface::AbstractModel *>()->get_model()).get_a();
}
// You cannot know at runtime what is contained in the model so you must iterate
// over possible model types and attach methods accordingly
void attach_model_specific_methods(py::object& obj){
using namespace teqp::cppinterface;
const auto& model = obj.cast<AbstractModel *>()->get_model();
auto setattr = py::getattr(obj, "__setattr__");
if (std::holds_alternative<vdWEOS1>(model)){
setattr("_a", py::object(&vdW_get_a));
}
}; But this doesn't compile. I would prefer to bind a lambda function since I have quite a few of these functions to add. How can one add runtime methods to an instance, dynamically? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
This link talks about it in detail for Python: https://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object-instance With pybind11, the 0-th method doesn't work ( Snippet: // You cannot know at runtime what is contained in the model so you must iterate
// over possible model types and attach methods accordingly
void attach_model_specific_methods(py::object& obj){
using namespace teqp::cppinterface;
const auto& model = obj.cast<AbstractModel *>()->get_model();
auto setattr = py::getattr(obj, "__setattr__");
auto MethodType = py::module_::import("types").attr("MethodType");
if (std::holds_alternative<vdWEOS1>(model)){
py::cpp_function get_a([](py::object& o){
return std::get<vdWEOS1>(o.cast<const teqp::cppinterface::AbstractModel *>()->get_model()).get_a();
});
setattr("get_a", MethodType(get_a, obj));
py::cpp_function get_b([](py::object& o){
return std::get<vdWEOS1>(o.cast<const teqp::cppinterface::AbstractModel *>()->get_model()).get_b();
});
setattr("get_b", MethodType(get_b, obj));
}
}; |
Beta Was this translation helpful? Give feedback.
This link talks about it in detail for Python: https://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object-instance
With pybind11, the 0-th method doesn't work (
py::cpp_function
doesn't have the__get__
method), but the first method works for me. It's verbose, and unpleasant to work with, but most importantly, it functions properly.Snippet: