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.
TypeError: No to_python (by-value) converter found for C++ type
This code works for me:
struct Base {
virtual ~Base() {};
virtual char const *hello() {
return "Hello. I'm Base.";
};
};
struct Derived : Base {
char const *hello() {
return "Hello. I'm Derived.";
};
Base &test(bool derived) {
static Base b;
static Derived d;
if (derived) {
return d;
} else {
return b;
}
}
};
BOOST_PYTHON_MODULE(wrapper)
{
using namespace boost::python;
class_<Base>("Base")
.def("hello", &Base::hello)
;
class_<Derived, bases<Base>>("Derived")
.def("test", &Derived::test, return_internal_reference<>())
;
}
Testing module:
>>> import wrapper
>>> d = wrapper.Derived()
>>> d.test(True).hello()
"Hello. I'm Derived."
>>> d.test(False).hello()
"Hello. I'm Base."
>>>
Object of self type in class - TypeError: No to_python (by-value) converter found for C++ type
Edit
I figured out that, replacing the line
boost::python::class_<Child>("Child")
by
boost::python::class_<Child, Child*>("Child")
in Wrapper.cpp solved my problem. The result is then as expected:
C:\Users\Visual Studio 2017\Projects\MinExBoostPython2\x64\Debug>Wrapper.py
0.0
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__instance_size__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'parent', 'val']
1.0
0.0
C:\Users\Visual Studio 2017\Projects\MinExBoostPython2\x64\Debug>
Hope it helps someone!
Boost Python No to_python converter found for std::string
Ok here is the entire to and from optional converter based on the original C++ sig post but rewritten to use the high level boost.python API (sorry about the weird spacing).
template<typename T>
struct optional_ : private boost::noncopyable
{
struct conversion :
public boost::python::converter::expected_from_python_type<T>
{
static PyObject* convert(boost::optional<T> const& value) {
using namespace boost::python;
return incref((value ? object(*value) : object()).ptr());
}
};
static void* convertible(PyObject *obj) {
using namespace boost::python;
return obj == Py_None || extract<T>(obj).check() ? obj : NULL;
}
static void constructor(PyObject *obj,
boost::python::converter::rvalue_from_python_stage1_data *data)
{
using namespace boost::python;
void *const storage =
reinterpret_cast<
converter::rvalue_from_python_storage<boost::optional<T> >*
>(data)->storage.bytes;
if(obj == Py_None) {
new (storage) boost::optional<T>();
} else {
new (storage) boost::optional<T>(extract<T>(obj));
}
data->convertible = storage;
}
explicit optional_() {
using namespace boost::python;
if(!extract<boost::optional<T> >(object()).check()) {
to_python_converter<boost::optional<T>, conversion, true>();
converter::registry::push_back(
&convertible,
&constructor,
type_id<boost::optional<T> >(),
&conversion::get_pytype
);
}
}
};
Convert type into python
Boost.Python call by reference : TypeError: No to_python (by-value) converter found for C++ type:
Boost::Python: no converter found for C++ type: boost::python::detail::kwds_proxy
user_add_wrapper(name, new_user)
tries to pass new_user
as a dictionary to user_add_wrapper()
, rather than passing the unpacked contents of new_user
. The new_user
dictionary needs to be unpacked. Additionally, calling the python::object
with an unpacked dictionary requires the first argument to be an unpacked boost::python::tuple
. To account for these requirements, invoke user_add_wrapper()
as follows:
user_add_wrapper(*bp::make_tuple(name), **new_user);
This behavior is part of the seamless interoperability provided by Boost.Python, but it is rather obscure and I only recall noticing it mentioned indirectly in the change log rather than the tutorial or reference.
Below is a complete minimal example. Given example.py
:
def user_add(name, givenname, sn):
print locals()
The following program invokes user_add()
by unpacking a dictionary:
#include <boost/python.hpp>
int main()
{
Py_Initialize(); // Start interpreter.
// Create the __main__ module.
namespace python = boost::python;
python::object main = python::import("__main__");
python::object main_namespace = main.attr("__dict__");
try
{
python::object example = python::import("example");
python::object example_namespace = example.attr("__dict__");
// Construct args.
std::string name = "Pythonist";
python::dict new_user;
new_user["givenname"] = "Test";
new_user["sn"] = "User";
// Invoke user_add by unpacking the new_user dictionary.
example_namespace["user_add"](*python::make_tuple(name), **new_user);
}
catch (const python::error_already_set&)
{
PyErr_Print();
}
}
And produces the following output:
{'givenname': 'Test', 'sn': 'User', 'name': 'Pythonist'}
(boost.python) Error exposing overloaded operator+(). TypeError: No to_python (by-value) converter found
It seems the matrix/vector library is using expression templates. In this case, and as you have remarked, operator+
is not returning a vector but a private type that represents the operation. The returned value is left trapped on the C++ side of things and can't be passed to Python as the private type is not registered.
Now I'm not too familiar with Boost.Python, but I think you can fix your problem with the return value policy. Passing a return_value_policy<to_python_value<DIM::Vector> >
as policy would force converting the returned type to DIM::Vector
, which you have registered. This would look like:
.def(self + self, return_value_policy<to_python_value<DIM::Vector> >())
Related Topics
How to Call a Cmake Function from Add_Custom_Target/Command
How to Assign a Value to the Pointer 'This' in C++
Advantages of Using Initializer List
How to Properly Delete a Pointer to Array
Fine Tuning Hough Line Function Parameters Opencv
Video Processing with Opencv in iOS Swift Project
What Is the Purpose of Unary Plus Operator on Char Array
C++ Get Description of an Exception Caught in Catch(...) Block
Where Does the -Dndebug Normally Come From
Exporting Static Data in a Dll
Clion C++ Can't Read/Open .Txt File in Project Directory
How to Embed the Gnu Octave in C/C++ Program
C++ Conversion Operator for Converting to Function Pointer
Why Are Designated Initializers Not Implemented in G++
Std::Vector Calling Destructor Multiple Times During Push_Back
Purpose of Perfect Forwarding for Callable Argument in Invocation Expression