最轻量、现代且推荐的方式是使用 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):
return a + b
def greet(name):
return f"Hello, {name}!"
立即学习“Python免费学习笔记(深入)”;
在 C++ 中加载并调用它:
#include
#include
Namespace py = pybind11;
int main() {
py::scoped_interpreter guard{}; // 初始化 Python 解释器
// 导入模块(路径需在 sys.path 中)
py::module_ math_mod = py::module_::import("math_utils");
// 调用函数
auto result = math_mod.attr("add")(10, 20).cast();
std::cout << "10 + 20 = " << result << "n";
auto msg = math_mod.attr("greet")("World").cast();
std::cout << msg << "n";
return 0;
}
⚠️ 注意:运行前需把 math_utils.py 所在目录加入 Python 搜索路径(例如用 py::module_::import("sys").attr("path").attr("append")("path/to/dir"))。
3. 直接执行 Python 脚本字符串(适合简单逻辑)
不依赖外部 .py 文件,直接运行 Python 代码片段:
py::exec(R"(
import numpy as np
x = np.Array([1, 2, 3])
print("Sum:", x.sum())
)");
适用于快速验证、动态表达式或胶水逻辑。但生产环境更推荐模块化导入(利于调试、复用和 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 环境一致性(解释器版本、路径、依赖包是否可见)和生命周期管理。