news 2026/3/14 0:19:01

如何通过 Py_Initialize 实现 C++ 对 Python 的嵌入调用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何通过 Py_Initialize 实现 C++ 对 Python 的嵌入调用

在现代软件开发中,性能(C++)灵活性(Python)的结合是许多大型项目的首选方案。无论是游戏引擎(如 Unreal Engine)还是高性能计算工具,通过在 C++ 中嵌入 Python 脚本,可以让用户在不重新编译程序的情况下编写插件或逻辑。

本文将带你走进 Python C API 的世界,重点介绍如何通过Py_Initialize实现 C++ 对 Python 的嵌入调用。


为什么要嵌入 Python?

  • 脚本化:允许用户自定义逻辑。

  • 快速原型:利用 Python 丰富的库(如 NumPy, SciPy)处理数据,而核心逻辑保持在 C++ 中。

  • 逻辑分离:将频繁变动的业务逻辑放在脚本层,核心底层放在 C++ 层。


核心流程图

在深入代码之前,我们先看下 C++ 调用 Python 的标准生命周期:


第一步:环境配置

要在 C++ 中使用 Python API,你需要:

  1. 头文件Python.h(位于 Python 安装目录的include文件夹)。

  2. 库文件python3x.lib(Windows)或libpython3x.so(Linux)。

注意:确保你的 C++ 编译位数(x64/x86)与 Python 安装版本一致,否则会报链接错误。


第二步:最简实现:Hello World

我们先从最简单的初始化和运行一段 Python 代码开始。

C++

#include <Python.h> #include <iostream> int main() { // 1. 初始化 Python 解释器 Py_Initialize(); if (!Py_IsInitialized()) { std::cerr << "Python 初始化失败!" << std::endl; return -1; } // 2. 执行简单的 Python 语句 PyRun_SimpleString("print('Hello from Python! I am embedded in C++.')"); PyRun_SimpleString("import platform; print('Python Version:', platform.python_version())"); // 3. 释放资源 Py_Finalize(); return 0; }

第三步:进阶——调用 Python 函数并传递参数

在实际项目中,我们通常需要加载一个.py文件,并调用其中的特定函数。

1. 准备 Python 脚本 (script.py)

Python

# script.py def add(a, b): print(f"Python 收到参数: {a} 和 {b}") return a + b

2. C++ 调用代码

调用过程涉及 Python 对象的引用计数管理,这是最容易出错的地方。

C++

#include <Python.h> #include <iostream> int main() { Py_Initialize(); // 将当前路径加入 Python 的搜索路径,否则找不到 script.py PyRun_SimpleString("import sys; sys.path.append('.')"); // 加载模块 PyObject* pModule = PyImport_ImportModule("script"); if (pModule) { // 获取函数对象 PyObject* pFunc = PyObject_GetAttrString(pModule, "add"); if (pFunc && PyCallable_Check(pFunc)) { // 创建参数元组 (3, 5) PyObject* pArgs = PyTuple_Pack(2, PyLong_FromLong(3), PyLong_FromLong(5)); // 调用函数 PyObject* pValue = PyObject_CallObject(pFunc, pArgs); if (pValue) { std::cout << "C++ 收到结果: " << PyLong_AsLong(pValue) << std::endl; Py_DECREF(pValue); } Py_DECREF(pArgs); } Py_XDECREF(pFunc); Py_DECREF(pModule); } else { PyErr_Print(); // 打印 Python 错误堆栈 } Py_Finalize(); return 0; }

核心 API 详解

函数功能
Py_Initialize()启动 Python 解释器并加载基本模块。
PyRun_SimpleString()执行单行 Python 代码,简单快捷,但无法获取返回值。
PyImport_ImportModule()动态加载一个.py模块。
PyObject_GetAttrString()从模块中获取属性(如函数、类)。
PyTuple_Pack()将 C++ 数据打包成 Python 的元组,用于函数传参。
Py_DECREF()减少引用计数。极其重要,否则会导致严重的内存泄漏。

避坑指南(经验总结)

  1. 路径问题:Python 解释器默认不搜索 C++ 可执行文件目录。务必使用sys.path.append('.')或设置PYTHONPATH环境变量。

  2. Debug/Release 陷阱:在 Windows 上,如果你编译 C++ 为 Debug 模式,它会尝试寻找python3x_d.lib。如果你的 Python 环境没有安装调试库,请确保 C++ 使用 Release 模式,或者手动修改宏定义。

  3. 引用计数:遵循“谁创建,谁负责”的原则。如果你通过PyImportPyObject_Get获得了对象,不用时必须Py_DECREF

  4. 多线程 (GIL):如果你的 C++ 程序是多线程的,且多个线程都要调用 Python,你需要处理GIL (Global Interpreter Lock)


总结

通过Py_Initialize嵌入 Python,为 C++ 程序打开了一扇通往无限库资源的大门。虽然 Python C API 的语法略显繁琐(尤其是内存管理),但它带来的灵活性是无与伦比的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/8 8:37:28

清华镜像源配置PyTorch安装加速技巧(含config指令)

清华镜像源加速 PyTorch 安装&#xff1a;高效构建深度学习环境的实战指南 在人工智能项目开发中&#xff0c;最让人沮丧的往往不是模型调不通&#xff0c;而是环境装不上。你有没有经历过这样的场景&#xff1f;深夜准备开始训练一个新模型&#xff0c;兴冲冲地敲下 pip inst…

作者头像 李华
网站建设 2026/3/14 3:54:08

GPU算力租赁新趋势:按需购买Token运行大模型

GPU算力租赁新趋势&#xff1a;按需购买Token运行大模型 在人工智能加速落地的今天&#xff0c;越来越多的研究者和开发者面临一个现实难题&#xff1a;想训练一个大模型&#xff0c;手头却没有A100&#xff1b;想跑通一次推理实验&#xff0c;却被复杂的CUDA环境配置卡住数小时…

作者头像 李华
网站建设 2026/3/5 13:21:29

VR自然灾害知识学习系统:系统化科普,筑牢防灾防线

全球气候多变、自然灾害频发背景下&#xff0c;提升公众灾害认知与防灾减灾能力成为保障生命财产安全的关键。自然灾害知识学习系统应运而生&#xff0c;以系统化、多元化内容呈现&#xff0c;构建覆盖11种常见自然灾害的综合学习平台&#xff0c;为公众便捷掌握灾害知识与应对…

作者头像 李华
网站建设 2026/3/12 20:07:22

一文说清并行计算核心要点:初学者友好版

并行计算入门&#xff1a;从“能不能拆”说起你有没有遇到过这样的场景&#xff1f;写好一个数据处理脚本&#xff0c;点下运行&#xff0c;然后眼睁睁看着它跑了整整三小时还没结束。CPU使用率却只有12%&#xff0c;四核八线程的处理器像在度假。这时候&#xff0c;最该问自己…

作者头像 李华
网站建设 2026/3/9 9:17:09

存储器接口电路在FPGA上的实现方法解析

FPGA上的存储器接口设计&#xff1a;从理论到实战的完整路径在现代高性能数字系统中&#xff0c;数据流动的速度往往决定了整个系统的上限。无论是工业相机每秒输出数GB的图像流&#xff0c;还是雷达前端持续不断的采样波形&#xff0c;这些海量数据都需要一个“中转站”——外…

作者头像 李华
网站建设 2026/3/14 7:39:10

Jupyter Notebook %time测量PyTorch单次执行耗时

Jupyter Notebook 中使用 %time 测量 PyTorch 单次执行耗时的实践与优化 在深度学习的实际开发中&#xff0c;我们常常会遇到这样的问题&#xff1a;某个模型前向传播为什么变慢了&#xff1f;刚写的自定义算子真的比原生实现更快吗&#xff1f;GPU 真的被充分利用了吗&#xf…

作者头像 李华