在现代软件开发中,将性能敏感的部分用 C++ 实现,动态变化的业务逻辑用 Python 编写是一种常见的做法。这种方法结合了 C++ 的高性能和 Python 的灵活性,适合需要频繁变更逻辑的场景,比如业务流程、规则引擎、数据处理等。以下是一些实现 C++ 和 Python 互相调用的常见方式和实际案例的建议:
1. 常见的 C++ 与 Python 交互方式
(1)嵌入 Python 到 C++(Python C API)
C++ 程序通过嵌入 Python 解释器来执行 Python 脚本。通过 Python C API,可以初始化 Python 解释器、加载脚本文件或模块,调用函数,并获取结果。
优点
- 高效,直接调用 Python 内部接口。
- 灵活,可以完全控制 Python 的执行环境。
缺点
- 代码复杂,Python C API 使用较为繁琐。
- 需要处理 Python 和 C++ 数据类型之间的转换。
示例代码
#include <Python.h> // Python C API 头文件
int main() {
// 初始化 Python 解释器
Py_Initialize();
// 加载 Python 脚本
PyObject* pModule = PyImport_ImportModule("my_script"); // 加载 my_script.py
if (!pModule) {
PyErr_Print();
return -1;
}
// 调用 Python 函数
PyObject* pFunc = PyObject_GetAttrString(pModule, "my_function"); // 获取 my_function 函数
if (pFunc && PyCallable_Check(pFunc)) {
// 构造函数参数
PyObject* pArgs = PyTuple_Pack(2, PyLong_FromLong(10), PyLong_FromLong(20));
PyObject* pValue = PyObject_CallObject(pFunc, pArgs); // 调用函数
// 处理返回值
if (pValue) {
long result = PyLong_AsLong(pValue); // 获取返回值
printf("Result from Python: %ld\n", result);
Py_DECREF(pValue);
}
Py_DECREF(pArgs);
} else {
PyErr_Print();
}
// 清理
Py_DECREF(pFunc);
Py_DECREF(pModule);
// 关闭 Python 解释器
Py_Finalize();
return 0;
}
(2)使用 Python/C++ 通信框架(如 pybind11 或 Boost.Python)
① pybind11
- 简介:
pybind11
是一个现代化的 C++11/14/17 库,专门用于在 C++ 和 Python 之间进行绑定。 - 优点:
- 代码简洁,易于使用。
- 支持现代 C++ 特性,例如类型推导和智能指针。
- 支持 Python 函数调用、C++ 函数/类暴露给 Python 等。
- 缺点:
- 需要额外的库支持。
- 性能可能略低于直接使用 Python C API。
示例代码
#include <pybind11/pybind11.h>
namespace py = pybind11;
// C++ 函数
int add(int a, int b) {
return a + b;
}
// 暴露给 Python
PYBIND11_MODULE(my_module, m) {
m.def("add", &add, "A function that adds two numbers");
}
- 编译生成 Python 模块:
c++ -O3 -Wall -shared -std=c++17 -fPIC `python3 -m pybind11 --includes` my_module.cpp -o my_module`python3-config --extension-suffix`
- Python 调用:
import my_module result = my_module.add(10, 20) print(f"Result from C++: {result}")
② Boost.Python
- 简介:
Boost.Python
是 Boost 库的一部分,提供了强大的 Python 和 C++ 互操作支持。 - 优点:
- 功能全面,支持复杂数据结构。
- 缺点:
- 编译依赖较重,配置复杂。
- 相比
pybind11
,代码冗长。
(3)通过 IPC 或 RPC 实现(如 ZeroMQ、gRPC)
这种方式通过进程间通信(IPC)或远程过程调用(RPC)实现 C++ 和 Python 的交互,适合分布式系统或异步调用场景。
优点
- 解耦 C++ 和 Python,跨语言协作更灵活。
- 支持分布式部署。
缺点
- 通信开销较高。
- 需要额外的通信框架。
示例:ZeroMQ
- 使用 C++ 实现服务端,通过 ZeroMQ 接收 Python 请求。
- 使用 Python 实现客户端,向 C++ 服务端发送任务请求。
- C++ 服务端示例:
#include <zmq.hpp> #include <string> #include <iostream> int main() { zmq::context_t context(1); zmq::socket_t socket(context, ZMQ_REP); socket.bind("tcp://*:5555"); while (true) { zmq::message_t request; socket.recv(request); std::string msg = std::string(static_cast<char*>(request.data()), request.size()); std::cout << "Received: " << msg << std::endl; zmq::message_t reply(5); memcpy(reply.data(), "World", 5); socket.send(reply); } return 0; }
- Python 客户端示例:
import zmq context = zmq.Context() socket = context.socket(zmq.REQ) socket.connect("tcp://localhost:5555") socket.send(b"Hello") message = socket.recv() print(f"Received reply: {message}")
其他框架:
- gRPC:用于跨语言的高性能 RPC 框架。
- HTTP/REST:通过 RESTful API 设计,让 C++ 提供服务,Python 调用。
(4)使用文件或数据库作为中介
通过文件(如 JSON、XML)或数据库传递数据,C++ 和 Python 分别读写。这种方式适合批处理任务,但不适用于高实时性场景。
2. 实际案例分析
(1)游戏引擎
- 游戏引擎(如 Unity 或 Unreal Engine)常用 C++ 实现核心渲染和物理引擎,用 Python 或 Lua 实现脚本和业务逻辑。
- 示例:
- 核心计算(如碰撞检测、图形绘制)用 C++ 实现。
- 游戏规则、AI 逻辑(如 NPC 行为)用 Python 脚本实现,支持动态加载和修改。
(2)金融交易系统
- 场景:
- C++ 实现高性能的交易撮合引擎。
- Python 用于快速开发业务逻辑,如风控规则、策略交易。
- 实现:
- C++ 使用
pybind11
暴露撮合功能。 - Python 调用接口,实现动态策略调整。
- C++ 使用
(3)机器学习与深度学习
- 场景:
- 训练阶段用 Python 编写(如 TensorFlow、PyTorch)。
- 推理阶段用 C++ 实现高性能部署。
- 实现:
- Python 训练模型,导出文件(如 ONNX 格式)。
- C++ 加载模型进行推理。
(4)Web 服务
- 场景:
- C++ 提供高性能计算服务(如视频转码)。
- Python 实现业务流程和 API 层(如 Flask、FastAPI)。
- 实现:
- Python 调用 C++ 的动态链接库,或通过 HTTP 调用 C++ 后端服务。
3. 总结与建议
选择方式
- 业务逻辑复杂、需要高性能调用:
- 推荐使用
pybind11
或Boost.Python
,简单易用。
- 推荐使用
- 分布式、异步调用场景:
- 推荐使用 ZeroMQ 或 gRPC。
- 简单任务或批处理场景:
- 使用文件或数据库作为中介。
开发建议
- 尽可能封装 C++ 的功能,提供清晰的接口给 Python 调用。
- 对于高性能需求,避免频繁的 C++/Python 互相调用,减少上下文切换开销。
- 注意数据类型转换的成本,尽量减少复杂的数据结构传递。
通过上述方法和案例,你可以根据实际需求选择合适的实现方式,将 C++ 和 Python 的优势结合起来,实现性能与灵活性的平衡!
标签:调用,socket,Python,业务流程,C++,pybind11,my From: https://blog.csdn.net/chenby186119/article/details/144185265