You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pybind11中复用其他项目已有的C++类型绑定?

问题

我正在使用Pybind11进行C到Python的绑定开发,现有两个C项目:Project A和Project B。Project A已完成Python绑定,并通过pip安装了对应的.whl包。我正在开发Project B的Python绑定,遇到两个需求:

  1. Project B中有一个函数的返回类型是Project A定义的complexType,该类型属性和方法繁多,不想重复绑定,希望复用Project A的已完成绑定。
  2. 需要绑定一个返回数据结构的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é

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 01:38:35