C++_python_相互之间的包含调用方法
1、C++的代码封装成插件或者封装成库,供python调用
C++ 代码完全可以封装成插件或库,供 Python 调用。这是 Python 生态中非常常见且成熟的做法,尤其在需要高性能计算、调用底层系统功能或复用已有 C/C++ 代码时。
以下是几种主流方法:
✅ 方法一:使用 pybind11(最推荐)
pybind11 是一个轻量级、现代的 C++ 库,专为将 C++ 代码暴露给 Python 而设计。语法简洁,支持 C++11 及以上特性(如类、重载、STL 容器等)。
示例步骤:
编写 C++ 代码(example.cpp): #include <pybind11/pybind11.h> int add(int a, int b){return a + b;} PYBIND11_MODULE(example, m){ m.doc()="pybind11 example plugin"; m.def("add", &add, "A function that adds two numbers");}编译为 Python 模块(使用 setup.py):
# setup.py from setuptools import setup, Extension from pybind11.setup_helpers import Pybind11Extension, build_ext ext_modules =[ Pybind11Extension("example", # 模块名["example.cpp"], # 源文件), ] setup(name="example", ext_modules=ext_modules, cmdclass={"build_ext": build_ext}, zip_safe=False, )构建并安装:
pip install pybind11 python setup.py build_ext --inplace 在 Python 中调用:
import example print(example.add(2, 3))# 输出 5✅ 优点:开发简单、性能高、自动类型转换、支持复杂 C++ 特性 🔧 依赖:需安装 pybind11(pip install pybind11) ✅ 方法二:使用 Python C API(官方底层接口)
直接使用 Python 提供的 C API 编写扩展模块(.so 或 .pyd)。这是最底层的方式,但代码繁琐。
示例(简化):
// example.c #include <Python.h> static PyObject* add(PyObject* self, PyObject* args){ int a, b;if(!PyArg_ParseTuple(args, "ii", &a, &b))return NULL;return PyLong_FromLong(a + b);} static PyMethodDef methods[]={{"add", add, METH_VARARGS, "Add two integers"}, {NULL, NULL, 0, NULL}}; static struct PyModuleDef module ={ PyModuleDef_HEAD_INIT, "example", NULL, -1, methods }; PyMODINIT_FUNC PyInit_example(void){return PyModule_Create(&module);}然后用 setup.py 编译(类似上面,但不用 pybind11)。
✅ 优点:不依赖第三方库
❌ 缺点:代码冗长、易出错、需手动管理引用计数
✅ 方法三:使用 Cython
Cython 是 Python 的超集,可将 .pyx 文件编译为 C 扩展。你可以在 Cython 中调用 C/C++ 代码,并暴露给 Python。
适合场景:已有 C++ 代码,想通过中间层包装。
✅ 优点:与 NumPy 集成好,适合数值计算 ⚠️ 注意:需学习 Cython 语法 ✅ 方法四:封装为 动态链接库 + ctypes / cffi
如果你不想生成 Python 扩展模块,也可以:
将 C++ 函数用 extern "C" 导出为 C 接口(避免 C++ 名称修饰) 编译为 .so(Linux/macOS)或 .dll(Windows) 在 Python 中用 ctypes 或 cffi 加载调用 示例(C++ 端):
// mathlib.cpp extern "C"{ int add(int a, int b){return a + b;}}编译:
g++ -shared -fPIC -o mathlib.so mathlib.cpp Python 调用:
import ctypes lib = ctypes.CDLL("./mathlib.so") lib.add.argtypes =(ctypes.c_int, ctypes.c_int) lib.add.restype = ctypes.c_int print(lib.add(2, 3))# 5✅ 优点:无需 Python 扩展构建系统,跨语言通用 ❌ 缺点:只能导出 C 风格接口,不支持类、异常、STL 等 C++ 特性 五、 📌 总结对比
表格
| 方法 | 易用性 | 性能 | 支持 C++ 特性 | 适用场景 |
|---|---|---|---|---|
| pybind11 | ⭐⭐⭐⭐⭐ | 高 | 完全支持(类、模板、STL) | 首选方案 |
| Python C API | ⭐⭐ | 高 | 需手动封装 | 底层开发/无第三方依赖 |
| Cython | ⭐⭐⭐ | 高 | 有限支持 | 数值计算、与 NumPy 集成 |
| ctypes/cffi | ⭐⭐⭐ | 中 | 仅 C 接口 | 快速调用简单函数 |
💡 建议
新项目 → 优先用 pybind11 已有 C 函数库 → 用 ctypes 快速集成 高性能数值计算 → 考虑 Cython 嵌入式/受限环境 → 用原生 C API 2、python的代码封装成插件或者封装成库,供C++调用
Python 代码可以封装成库或插件供 C++ 调用,但通常需要借助一些特定的技术或工具。以下是几种主流方法:
方法一:使用 Python/C API(官方接口)
这是 Python 官方提供的 C 接口,C++ 可以通过它嵌入 Python 解释器并调用 Python 代码。
步骤简述:
在 C++ 项目中链接 Python 的动态库(如 libpython3.x.so 或 python3x.lib)。 使用 Py_Initialize() 初始化解释器。 用 PyRun_SimpleString() 或 PyObject_CallObject() 等函数加载并调用 Python 模块/函数。 处理 Python 对象与 C++ 数据类型的转换。 最后调用 Py_Finalize() 清理。 示例(简化):
#include <Python.h> int main(){ Py_Initialize(); PyRun_SimpleString("import sys; sys.path.append('.')"); PyRun_SimpleString("import mymodule"); PyRun_SimpleString("mymodule.my_function()"); Py_Finalize();return0;}✅ 优点:直接、灵活 ❌ 缺点:需手动管理引用计数、错误处理复杂、依赖 Python 环境 方法二:使用 pybind11(推荐)
虽然 pybind11 主要用于将 C++ 暴露给 Python,但它也支持反向操作——在 C++ 中嵌入 Python。
不过更常见的是:将核心逻辑写成 C++,用 pybind11 暴露给 Python;如果已有 Python 代码想被 C++ 调用,仍建议用 Python/C API 或生成可执行接口。
但 pybind11 本身不直接“让 C++ 调用任意 Python 函数”变得简单,它更擅长反向绑定。
方法三:将 Python 封装为 独立服务(进程间通信)
如果不想在 C++ 中嵌入 Python 解释器,可以把 Python 代码做成一个独立的服务(如 HTTP API、gRPC、ZeroMQ、共享内存、管道等),C++ 通过 IPC 调用。
例如:
Python 启动一个 Flask/FastAPI 服务 C++ 用 libcurl 发送 HTTP 请求调用该服务 ✅ 优点:解耦、跨语言、稳定 ❌ 缺点:有网络开销、部署复杂度略高 方法四:将 Python 编译为 共享库(较难)
有一些工具尝试将 Python 编译成原生二进制(如 Cython、Nuitka、Shiv、PyOxidizer),但:
Nuitka 可以将 Python 编译成 C++ 扩展模块(.so / .dll),但这些模块仍是供 Python 调用的,不是直接供 C++ 调用。 目前没有成熟方案能将任意 Python 代码直接编译成标准 C++ 可链接的 .so 库(像 C 函数那样被 extern "C" 调用)。 所以这条路通常不可行,除非你用 Cython 重写部分代码为 .pyx 并导出 C 接口。
实用建议:
| 场景 | 推荐方案 |
|---|---|
| C++ 需频繁调用少量 Python 脚本 | 使用 Python/C API 嵌入解释器 |
| Python 逻辑复杂、需长期运行 | 将 Python 做成 微服务,C++ 通过网络调用 |
| 性能敏感、低延迟 | 重写关键部分为 C++,用 pybind11 让 Python 调用 C++(反向) |
| 不想依赖 Python 运行时 | 考虑用 Cython 重写并导出 C 接口 |
补充:构建注意事项
C++ 项目需链接 Python 开发库(如 Ubuntu 上 sudo apt install python3-dev) 注意 Python 版本匹配(3.8/3.9/3.10...) 多线程环境下需注意 GIL(全局解释器锁)