如何在Boost-Python中用C++实现继承str的Python类并支持__truediv__
问题描述
希望通过Boost-Python让C函数返回继承自Python内置str类的对象,已实现「Python端定义子类+ C调用实例化」的可行方案,但直接在C中定义继承py::str的类时,__truediv__方法无法正常工作,报错ValueError: character U+5555eaa0 is not in range [U+0000; U+10ffff],需解决纯C端的正确实现方式。
可行的Python类+ C++调用方案
Python模块定义(mystr.py)
class MyStr(str): def __truediv__(self, other): return self + other
C++调用实现
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"]; }
Python调用验证
a = AsMyStr("Hello") b = " World" print(a / b) # 输出:Hello World
有问题的纯C++实现方案
C++类定义
class MyStr : public py::str { public: MyStr(py::object const &o) : py::str(o) {} MyStr __truediv__(py::object other) { return MyStr(*this + other); } };
模块暴露代码
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__) ; }
Python调用报错
a = MyStr("Hello") b = " World" print(a / b) # 错误:ValueError: character U+5555eaa0 is not in range [U+0000; U+10ffff]
正确的纯C++实现方案
问题根源:Python内置不可变类型(如str)的对象模型特殊,直接在C++中继承py::str会破坏内存管理逻辑,导致非法内存访问。以下是两种可靠实现方式:
方式1:通过Boost-Python包装Python原生str子类
#include <boost/python.hpp> namespace py = boost::python; struct MyStrOps { static py::object truediv(py::self self, py::object other) { // 拼接字符串后,用当前类实例化新对象返回 py::object str_result = py::str(self) + py::str(other); return py::type(self)(str_result); } }; BOOST_PYTHON_MODULE(MyStr) { // 获取Python原生str类型作为父类 py::object str_type = py::import("__builtin__").attr("str"); // 定义MyStr类并绑定方法 py::class_<py::object, boost::noncopyable>("MyStr", str_type, py::init<py::object>()) .def("__truediv__", &MyStrOps::truediv) ; }
方式2:用类型转换器关联C++对象与Python str子类
#include <boost/python.hpp> namespace py = boost::python; // C++端数据存储类 class MyStr { public: MyStr(const std::string& s) : content_(s) {} std::string content_; }; // 自定义类型转换器:将C++ MyStr转为Python的MyStr实例 struct MyStrToPython { static PyObject* convert(const MyStr& ms) { // 获取Python端定义的MyStr类(需确保mystr模块可导入) py::object my_str_cls = py::import("mystr").attr("MyStr"); return py::incref(my_str_cls(ms.content_).ptr()); } }; BOOST_PYTHON_MODULE(MyStr) { // 注册类型转换器 py::to_python_converter<MyStr, MyStrToPython>(); // 暴露C++类及方法 py::class_<MyStr>("MyStr", py::init<const std::string&>()) .def("__truediv__", [](const MyStr& self, const std::string& other) { return MyStr(self.content_ + other); }) ; }
内容的提问来源于stack exchange,提问作者Jan Christoph Terasa
相关产品推荐
相关产品推荐

