I need to build python bindings for a C++ codebase. I use boost::python and I ran into problems trying to expose classes containing functions using and returning templates. Here is a typical example
class Foo
{
public:
Foo();
template<typename T> Foo& setValue(
const string& propertyName, const T& value);
template<typename T> const T& getValue(
const string& propertyName);
};
Typical T are string, double, vector.
After reading the documentation, I tried using thin wrappers for every type used. Here are the wrappers for string and double and the corresponding class declaration.
Foo & (Foo::*setValueDouble)(const std::string&,const double &) =
&Foo::setValue;
const double & (Foo::*getValueDouble)(const std::string&) =
&Foo::getValue;
Foo & (Foo::*setValueString)(const std::string&,const std::string &) =
&Foo::setValue;
const std::string & (Foo::*getValueString)(const std::string&) =
&Foo::getValue;
class_<Foo>("Foo")
.def("setValue",setValueDouble,
return_value_policy<reference_existing_object>())
.def("getValue",getValueDouble,
return_value_policy<copy_const_reference>())
.def("getValue",getValueString,
return_value_policy<copy_const_reference>())
.def("setValue",setValueString,
return_value_policy<reference_existing_object>());
It compiles ok but when I try to use the python bindings, I get a C++ exception.
>>> f = Foo()
>>> f.setValue("key",1.0)
>>> f.getValue("key")
Traceback (most recent call last):
File "<stdin>", line 1, in ?
RuntimeError: unidentifiable C++ exception
Interestingly, when I only expose Foo for double or string value, i.e
class_<Foo>("Foo")
.def("getValue",getValueString,
return_value_policy<copy_const_reference>())
.def("setValue",setValueString,
return_value_policy<reference_existing_object>());
It works fine. Am I missing something?
This may not be related to your problem directly but I would not trust function signature casting with templates like that. I would have wrapped it like this:
class_<Foo>("Foo")
.def("setValue", &Foo::setValue<double>,
return_value_policy<reference_existing_object>())
.def("getValue", &Foo::getValue<double>,
return_value_policy<copy_const_reference>())
.def("getValue", &Foo::getValue<std::string>,
return_value_policy<copy_const_reference>())
.def("setValue", &Foo::setValue<std::string>,
return_value_policy<reference_existing_object>());
If that does not work, you may need to create some shim functions:
Foo& setValueDouble(foo& self, const string& propertyName, const double value)
{
return self.setValue(propertyName, value)
}
...
and export those as thought they were member functions.
Exporting multiple function overloads to the same name is a perfectly valid thing to do in Boost::Python, so I do not think that that is the problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With