pybind11无法识别PyObject*为Python对象的原因及解决方法
Pybind11返回PyObject*报错:TypeError: Unregistered type : _object的原因与解决方法
问题场景
尝试用以下C++代码基于pybind11构建扩展库:
#include <pybind11/pybind11.h> namespace py = pybind11; PyObject* func() { return Py_BuildValue("iii", 1, 2, 3); } PYBIND11_MODULE(example, m) { m.def("func", &func); }
运行Python代码调用时:
import example print(example.func())
触发错误:
TypeError: Unregistered type : _object The above exception was the direct cause of the following exception: Traceback (most recent call last): File "<string>", line 1, in <module> TypeError: Unable to convert function return value to a Python type! The signature was () -> _object
报错原因
- pybind11的函数绑定系统默认不识别原始
PyObject*类型,它需要明确的类型转换规则,直接返回PyObject*会导致pybind11无法完成类型映射,触发“未注册类型”错误。 Py_BuildValue返回的是底层Python对象指针,但pybind11需要将其包装为自身的py::object类型才能正确管理生命周期和类型转换,直接传递原始指针会导致类型不匹配。
解决方法
方法一:用pybind11包装原始PyObject*
修改C++代码,将返回类型改为py::object,并用py::reinterpret_steal接管Py_BuildValue返回对象的所有权:
#include <pybind11/pybind11.h> namespace py = pybind11; py::object func() { // 接管Python C API创建的对象所有权,让pybind11管理生命周期 return py::reinterpret_steal<py::object>(Py_BuildValue("iii", 1, 2, 3)); } PYBIND11_MODULE(example, m) { m.def("func", &func); }
方法二:使用pybind11原生API构造返回值
放弃直接调用Python C API,改用pybind11提供的接口创建Python对象,类型会自动被识别:
#include <pybind11/pybind11.h> #include <pybind11/tuple.h> // 包含元组构造的头文件 namespace py = pybind11; py::tuple func() { return py::make_tuple(1, 2, 3); } PYBIND11_MODULE(example, m) { m.def("func", &func); }
测试验证
修改后重新编译扩展库,运行原Python代码会正常输出:
import example print(example.func()) # 输出:(1, 2, 3)
内容的提问来源于stack exchange,提问作者Vad Sim
相关产品推荐
相关产品推荐

