如何在Pybind11中复用其他项目已有的C++类型绑定?
问题
我正在使用Pybind11进行C到Python的绑定开发,现有两个C项目:Project A和Project B。Project A已完成Python绑定,并通过pip安装了对应的.whl包。我正在开发Project B的Python绑定,遇到两个需求:
- Project B中有一个函数的返回类型是Project A定义的
complexType,该类型属性和方法繁多,不想重复绑定,希望复用Project A的已完成绑定。 - 需要绑定一个返回数据结构的C++函数,该结构的成员之一是另一个已安装绑定包的
complexType对象。
附Project B绑定示例代码:
#include <pybind11/pybind11.h> #include "ProjectA/complexType.h" namespace py = pybind11; complexType myfcn(const std::string &filename) { // 函数体 return complexTypeObject; } PYBIND11_MODULE(mymodule, m) { // 模块文档 m.doc() = "Doc."; // 我不想这么做,因为Python无法识别complexType的属性,且我不想重复绑定该类 // py::class_<ProjectA::complexType>(m, "complexType"); // 函数绑定: m.def("myfcn", &myfcn, "My fcn description"); }
解决方案
核心逻辑是复用Project A已有的Python类型绑定,无需在Project B中重复定义类的所有属性和方法,以下是两种可行方法:
方法一:直接导入Project A的Python类型并关联
通过在C绑定代码中导入已安装的Project A Python模块,获取其导出的complexType类型,再将C类型与该Python类型关联:
#include <pybind11/pybind11.h> #include "ProjectA/complexType.h" namespace py = pybind11; complexType myfcn(const std::string &filename) { // 函数体 return complexTypeObject; } // 需要绑定的结构体示例 struct ResultStruct { int code; ProjectA::complexType detail; }; PYBIND11_MODULE(mymodule, m) { m.doc() = "Doc."; // 1. 导入Project A的Python模块(假设模块名为project_a) py::module_ project_a = py::module_::import("project_a"); // 2. 获取Project A中已绑定的complexType类(假设导出类名为ComplexType) py::handle complex_type_handle = project_a.attr("ComplexType"); // 3. 将C++的ProjectA::complexType与已有的Python类型关联 py::class_<ProjectA::complexType>(m, complex_type_handle); // 绑定结构体,直接复用已关联的complexType类型 py::class_<ResultStruct>(m, "ResultStruct") .def(py::init<>()) .def_readwrite("code", &ResultStruct::code) .def_readwrite("detail", &ResultStruct::detail); // 绑定函数,返回值会自动使用已有的类型绑定 m.def("myfcn", &myfcn, "My fcn description"); }
方法二:复用Project A的类型转换器(底层方案)
如果Project A的绑定库导出了类型转换逻辑(比如提供了绑定头文件),可以直接在Project B中引入,无需手动导入模块:
#include <pybind11/pybind11.h> #include "ProjectA/complexType.h" // 引入Project A的绑定头文件,其中包含complexType的类型转换器 #include "ProjectA/pybind_bindings.h" namespace py = pybind11; complexType myfcn(const std::string &filename) { return complexTypeObject; } struct ResultStruct { int code; ProjectA::complexType detail; }; PYBIND11_MODULE(mymodule, m) { m.doc() = "Doc."; // 无需重新定义complexType,直接使用Project A的类型转换器 py::class_<ResultStruct>(m, "ResultStruct") .def(py::init<>()) .def_readwrite("code", &ResultStruct::code) .def_readwrite("detail", &ResultStruct::detail); m.def("myfcn", &myfcn, "My fcn description"); }
注意事项
- 确保Project A的Python模块在运行时可被正常导入(已通过pip正确安装)。
- 如果Project A导出的类名与C++类名不一致,需调整代码中
attr()的参数。 - 若Project A的绑定使用了
py::module_local(),需修改为全局可见的绑定策略,否则类型无法跨模块复用。
内容的提问来源于stack exchange,提问作者José
相关产品推荐
相关产品推荐

