Boost.Python实现C++嵌入Python时MyCallback类未注册报错如何解决
问题原因
两个报错的核心是你定义的BOOST_PYTHON_MODULE(mylib)绑定代码从未被执行,对应的类、智能指针转换规则都没有注册到当前运行的Python解释器中:
- 第一个
No to_python (by-value) converter found for C++ type: class boost::shared_ptr<class MyCallback>报错:你写的register_ptr_to_python规则绑定在mylib模块下,模块未加载时规则不生效,Boost.Python无法完成C++智能指针到Python对象的转换。 - 第二个
No Python class registered for C++ class class MyCallback报错:改用原始指针传参时,同样因为MyCallback类的绑定信息未注册,Boost.Python找不到对应的Python类映射。
修复步骤
- 首先在全局作用域声明模块初始化函数的C导出符号,避免Windows下VC++编译器修改函数名导致找不到入口:
extern "C" __declspec(dllexport) PyObject* PyInit_mylib();
- 在
Py_Initialize()调用后、导入你的Python业务模块前,先注册并加载你写的mylib绑定模块,触发绑定规则注册:
Py_Initialize(); // 注册自定义模块初始化函数 PyImport_AppendInittab("mylib", &PyInit_mylib); // 导入模块,执行你写的类、转换器注册代码 boost::python::import("mylib"); // 后面再导入你的业务模块 auto mymodule = boost::python::import("mypackage.mymodule");
- 原有传参逻辑无需修改,直接传
shared_ptr<MyCallback>对象即可,你写的register_ptr_to_python规则加载后会自动完成转换。 - 补充异常处理的空指针判断:
PyErr_Fetch返回的错误对象可能为NULL,直接调用extract会触发崩溃,建议先判断pvalue != nullptr再提取错误信息,同时补充错误对象的释放逻辑避免内存泄漏。
完整修改后的C++代码
#include <boost/python.hpp> #include <boost/make_shared.hpp> #include <iostream> using namespace boost; using namespace boost::python; using namespace boost::python::api; // 声明模块初始化函数的C导出符号 extern "C" __declspec(dllexport) PyObject* PyInit_mylib(); class MyCallback { public: void on_order(boost::python::object order) { // 测试打印order的name属性 std::cout << "收到订单:" << extract<std::string>(order.attr("name")) << std::endl; } }; BOOST_PYTHON_MODULE(mylib) { boost::python::class_<MyCallback>("MyCallback") .def("on_order", &MyCallback::on_order) ; boost::python::register_ptr_to_python<boost::shared_ptr<MyCallback>>(); } int main() { try { Py_SetPythonHome(const_cast<wchar_t*>(L"C:/Users/xxxxxx/anaconda3/envs/py36_64")); Py_Initialize(); // 加载自定义绑定模块 PyImport_AppendInittab("mylib", &PyInit_mylib); boost::python::import("mylib"); auto mymodule = boost::python::import("mypackage.mymodule"); auto my_class = mymodule.attr("MyClass"); try { auto myCallback = boost::make_shared<MyCallback>(); auto obj = my_class("John", 123, myCallback); obj.attr("send_order")("product1"); } catch (...) { PyObject *ptype, *pvalue, *ptraceback; PyErr_Fetch(&ptype, &pvalue, &ptraceback); if (pvalue) { std::wstring strErrorMessage = boost::python::extract<std::wstring>(pvalue); // 打印错误信息逻辑自行补充 } // 释放错误对象 Py_XDECREF(ptype); Py_XDECREF(pvalue); Py_XDECREF(ptraceback); } Py_Finalize(); } catch (...) { PyObject *ptype, *pvalue, *ptraceback; PyErr_Fetch(&ptype, &pvalue, &ptraceback); if (pvalue) { std::wstring strErrorMessage = boost::python::extract<std::wstring>(pvalue); } Py_XDECREF(ptype); Py_XDECREF(pvalue); Py_XDECREF(ptraceback); } return 0; }
内容的提问来源于stack exchange,提问作者user1633272
相关产品推荐
相关产品推荐

