Boost.Python call by reference : TypeError: No to_python (by-value) converter found for C++ type:
Change B.do_something(a);
to B.do_something(boost::ref(a));
.
See Calling Python Functions and Methods in the boost manual.
Kai
Updated on June 14, 2022Comments
-
Kai almost 2 years
I'm trying to expose my C++ Classes to Python using Boost.Python. Here is a simplyfied version of what i'm trying to do:
I have a class A deriving from boost::noncopyable and a second class B with a method that takes a reference to A as an argument.
class A : boost::noncopyable { /*...*/ }; class B { public: virtual void do_something(A& a) { /*...*/ } };
I'm exposing the classes as follows:
/* Wrapper for B, so B can be extended in python */ struct BWrap : public B, wrapper<B> { void do_something(A &a) { if (override do_something = this->get_override("do_something")) { do_something(a); return; } else { B::do_something(a); } } void default_do_something(A& a) { this->B::do_something(a); } }; BOOST_PYTHON_MODULE(SomeModule) { class_<A, boost::noncopyable>("A"); class_<BWrap, boost::noncopyable>("B") .def("do_something", &B::do_something, &BWrap::default_do_something) ; }
I extend B in python like this:
test.py:
import SomeModule class BDerived(SomeModule.B): def do_something(self, a): pass
and call the extended B like this:
try { py::object main = py::import("__main__"); \ py::object global(main.attr("__dict__")); \ py::object result = py::exec_file("test.py", global, global); \ py::object pluginClass = global["BDerived"]; \ py::object plugin_base = pluginClass(); \ B& plugin = py::extract<B&>(plugin_base) BOOST_EXTRACT_WORKAROUND; A a; B.do_something(a); } catch (py::error_already_set) { PyErr_Print(); }
However this results in an error message:
TypeError: No to_python (by-value) converter found for C++ type: A
If
A
isn't derived fromboost::noncopyable
the code runs without any errors but the argument a indo_something(A& a)
gets copied during the function call even though it's passed in by reference. But just removing the noncopyable requirement onA
isn't an option since it's there for a reason.Any suggestions how to solve the problem?
Thanks.
-
Kai about 13 yearsThanks a lot! You gave me the right hint. Even though I had to change it in the wrapper class BWrap
do_something(boost::ref(a));
and not when callingB.do_something(a);
. Unbelievable that even hours of googling never gave me that hint. Thanks again!