C++如何调用Python脚本?(pybind11示例)

17次阅读

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

C++如何调用Python脚本?(pybind11示例)

用 C++ 调用 Python 脚本,最轻量、现代且推荐的方式是使用 pybind11 —— 它不是简单地“执行脚本”,而是让 C++ 和 Python 对象在运行时直接互通,支持函数调用、类型转换、异常传递,且无需启动独立 Python 进程。

1. 基础准备:安装 pybind11 并配置编译环境

pybind11 是头文件库,无需编译安装(也可用 vcpkg / conan / pip install pybind11)。关键是确保 C++ 项目能链接到 Python 解释器:

  • linux/macOS:需安装 Python3 开发包(如 python3-devpython3-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 环境一致性(解释器版本、路径、依赖包是否可见)和生命周期管理。

text=ZqhQzanResources