1、C++的代码封装成插件或者封装成库,供python调用
C++ 代码完全可以封装成插件或库,供 Python 调用。这是 Python 生态中非常常见且成熟的做法,尤其在需要高性能计算、调用底层系统功能或复用已有 C/C++ 代码时。
以下是几种主流方法:
✅ 方法一:使用 pybind11(最推荐)
pybind11 是一个轻量级、现代的 C++ 库,专为将 C++ 代码暴露给 Python 而设计。语法简洁,支持 C++11 及以上特性(如类、重载、STL 容器等)。
示例步骤:
编写 C++ 代码(example.cpp):
bash
#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):
bash
# 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,
)
构建并安装:
bash
pip install pybind11
python setup.py build_ext --inplace
在 Python 中调用:
bash
import example
print(example.add(2, 3)) # 输出 5
✅ 优点:开发简单、性能高、自动类型转换、支持复杂 C++ 特性
🔧 依赖:需安装 pybind11(pip install pybind11)
✅ 方法二:使用 Python C API(官方底层接口)
直接使用 Python 提供的 C API 编写扩展模块(.so 或 .pyd)。这是最底层的方式,但代码繁琐。
示例(简化):
bash
// 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++ 端):
bash
// mathlib.cpp
extern "C" {
int add(int a, int b) {
return a + b;
}
}
编译:
bash
g++ -shared -fPIC -o mathlib.so mathlib.cpp
Python 调用:
bash
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() 清理。
示例(简化):
bash
#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();
return 0;
}
✅ 优点:直接、灵活
❌ 缺点:需手动管理引用计数、错误处理复杂、依赖 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(全局解释器锁)