Boost-Python: Expose a class to Python which is a subclass of a Python class (str)
I am trying to have a Boost Python function return a Python object which is a subclass of a Python builtin class (here str
):
My first method involves creating the class in a Python module, mystr.py
:
class MyStr(str):
def __truediv__(self, other):
return self + other
I then import that module using Boost, and then to return a python object of that type I use somehting along these lines in C++, importing the module and calling py::exec
:
py::object AsMyStr(std::string const &s)
{
py::object my_str = py::import("mystr");
py::dict my_namespace(my_str.attr("__dict__"));
my_namespace["_MYSTR_test"] = s;
py::exec(
"_MYSTR_test = MyStr(_MYSTR_test)\n",
my_namespace, my_namespace);
return my_namespace["_MYSTR_test"];
}
Exposing this funtion in a Boost-Python module, this correctly gives me a MyStr
instance on the Python side, which can be used accordingly:
a = AsMyStr("Hello")
b = " World"
print(a / b)
# "Hello World"
I just wonder if the subclassing of str
can be done on the Boost-Python side of things in C++. I cannot manage to get __truediv__
to work in that case:
class MyStr : public py::str
{
public:
MyStr(py::object const &o) : py::str(o)
MyStr __truediv__(other)
{
return MyStr(*this + other);
}
}
Exposing it as a module
BOOST_PYTHON_MODULE(MyStr)
{
py::class_<MyStr, py::bases<py::str>>("MyStr", py::no_init)
.def(py::init<py::object const &>())
.def("__truediv__", &MyStr::__truediv__)
;
}
But using this class on the Python side leads to:
a = MyStr("Hello")
b = " World"
print(a / b)
# ValueError: character U+5555eaa0 is not in range [U+0000; U+10ffff]
How do I have to define and expose the class MyStr
in the C++ implementation to return on the Python side a "true" MyStr which is a subclass of str
?
I uploaded the code to https://gitlab.com/kohlrabi/learn-boost-python, the branch master
contains the first solution, the branch cpp_class
the second, non-working solution.
Comments
Post a Comment