最轻量、现代且推荐的方式是使用 pybind11——它实现 C++ 与 Python 运行时直接互通,支持函数调用、类型转换和异常传递,无需启动独立进程。

用 C++ 调用 Python 脚本,最轻量、现代且推荐的方式是使用 pybind11 —— 它不是简单地“执行脚本”,而是让 C++ 和 Python 对象在运行时直接互通,支持函数调用、类型转换、异常传递,且无需启动独立 Python 进程。
1. 基础准备:安装 pybind11 并配置编译环境
pybind11 是头文件库,无需编译安装(也可用 vcpkg / conan / pip install pybind11)。关键是确保 C++ 项目能链接到 Python 解释器:
- Linux/macOS:需安装 Python3 开发包(如
python3-dev或python3-devel) - Windows:建议用 Visual Studio + Python 官方发行版(避免 Miniconda/Anaconda 的路径问题)
- CMake 是最稳妥的构建方式,pybind11 提供
find_package(pybind11)支持
2. 最小可运行示例:从 C++ 调用 Python 函数
假设你有一个 Python 文件 math_utils.py:
def add(a, b):<br> return a + b<br><br>def greet(name):<br> return f"Hello, {name}!"
立即学习“Python免费学习笔记(深入)”;
在 C++ 中加载并调用它:
#include <pybind11/embed.h><br>#include <iostream><br>namespace py = pybind11;<br><br>int main() {<br> py::scoped_interpreter guard{}; // 初始化 Python 解释器<br><br> // 导入模块(路径需在 sys.path 中)<br> py::module_ math_mod = py::module_::import("math_utils");<br><br> // 调用函数<br> auto result = math_mod.attr("add")(10, 20).cast<int>();<br> std::cout << "10 + 20 = " << result << "\n";<br><br> auto msg = math_mod.attr("greet")("World").cast<std::string>();<br> std::cout << msg << "\n";<br><br> return 0;<br>}
⚠️ 注意:运行前需把 math_utils.py 所在目录加入 Python 搜索路径(例如用 py::module_::import("sys").attr("path").attr("append")("path/to/dir"))。
3. 直接执行 Python 脚本字符串(适合简单逻辑)
不依赖外部 .py 文件,直接运行 Python 代码片段:
py::exec(R"(<br> import numpy as np<br> x = np.array([1, 2, 3])<br> print("Sum:", x.sum())<br>)");
适用于快速验证、动态表达式或胶水逻辑。但生产环境更推荐模块化导入(利于调试、复用和 IDE 支持)。
4. 关键细节与避坑提示
-
Python 解释器生命周期:必须在主线程中初始化
py::scoped_interpreter,且不能跨线程共享 Python GIL —— 多线程需手动加锁(py::gil_scoped_acquire) -
路径问题最常见:C++ 启动时的当前工作目录 ≠ Python 模块搜索路径,默认不包含当前目录;务必显式添加
sys.path -
类型转换自动但有限:int/float/string/list/dict 自动转换;NumPy 数组、自定义类需额外绑定或使用
py::array等专用接口 -
异常处理:Python 抛出异常会自动转为
py::error_already_set,可用try-catch捕获并转为 C++ 异常
不复杂但容易忽略:真正打通的关键不在语法,而在 Python 环境一致性(解释器版本、路径、依赖包是否可见)和生命周期管理。










