当前位置: 首页
编程语言
Boost.Python嵌入教程:从C/C++调用Python代码

Boost.Python嵌入教程:从C/C++调用Python代码

热心网友 时间:2026-06-22
转载

使用Boost Python可将Python解释器嵌入C++程序,并辅以Python CAPI弥补不足。构建时链接Boost Python和Python库,通过handle和object类自动管理引用计数,避免内存泄漏。提供eval、exec、exec_file函数运行Python代码,支持导入模块。异常时抛出error_already_set,可用PyEr

使用解释器

看到这里,你应该已经掌握了如何用 Boost.Python 从 Python 调用 C++ 代码。但现实总要更复杂一些——有时候你需要反过来:从 C++ 端去调用 Python 代码。这就需要你把 Python 解释器“嵌入”到 C++ 程序中。

目前,Boost.Python 并没有把嵌入所需的一切功能都打包好,所以你还需要借助 Python/C API 来补上那些缺口。不过,Boost.Python 已经让嵌入这件事变得容易了不少,而且可以期待的是,在后续版本中,你甚至完全不需要碰 Python/C API。这一点值得持续关注。

构建嵌入式程序

想要把 Python 嵌入到你的程序里,链接时需要连上 Boost.Python 和 Python 自身的运行时库。

Boost.Python 的库有两个变体,都放在 Boost 的 /libs/python/build/bin-stage 子目录下。在 Windows 上,发布版叫 boost_python.lib,调试版叫 boost_python_debug.lib。如果你找不到对应库,那大概率是还没构建 Boost.Python。

Python 的库则在 Python 目录下的 /libs 子目录中。Windows 上它叫 pythonXY.lib,其中 XY 对应你的 Python 主版本号。

另外,记得把 Python 的 /include 子目录加到包含路径里。

用 Jamfile 来组织这一切的话,大致是这样:

projectroot c:projectsembedded_program ; # location of the program
# bring in the rules for python
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
exe embedded_program # name of the executable
: # sources
embedded_program.cpp
: # requirements
boost_python
c:boostlibspython$(PYTHON_PROPERTIES)
$(PYTHON_LIB_PATH)
$(PYTHON_EMBEDDED_LIBRARY) ;

入门

能构建工程是好事,但还缺真正要运行的东西。想要把 Python 解释器嵌入到你的 C++ 程序里,需要按顺序完成四个步骤:

  1. #include
  2. 调用 Py_Initialize() 启动解释器,并创建 __main__ 模块。
  3. 调用其他 Python C API 例程来使用解释器。
  4. (注意:此时还不能调用 Py_Finalize() 来停止解释器。这个问题可能会在未来的 boost.python 版本中得到解决。)

现在我们可以把解释器嵌入到程序里了,接下来看看怎么用它。

使用解释器

你可能已经知道,Python 中的对象是引用计数的。Python C API 的 PyObject 自然也沿用这一机制。但区别在于:Python 内部引用计数是全自动的,而 Python C API 却要求你手动处理。这很麻烦,而且一旦碰上 C++ 异常,手动管理更是容易出问题。好在 Boost.Python 提供了 handleobject 类模板,帮我们把这一过程自动化了。

运行 Python 代码

Boost.Python 提供了三个函数,用来从 C++ 端运行 Python 代码:

object eval(str expression, object globals = object(), object locals = object())
object exec(str code, object globals = object(), object locals = object())
object exec_file(str filename, object globals = object(), object locals = object())

eval 计算给定的表达式并返回结果值;exec 执行一段代码(通常是一组语句),它不返回值(但你可以通过字典拿到结果);exec_file 则直接执行一个文件中的代码。

globalslocals 参数都是 Python 字典,用于指定代码运行时的全局与局部变量上下文。在大多数场景下,直接拿 __main__ 模块的命名空间字典来当这两个参数就足够了。

此外,Boost.Python 还提供了导入模块的功能:

object import(str name)

它会导入指定的 Python 模块(必要时会将其加载到当前进程中),然后返回该模块对象。

看个例子:导入 __main__ 模块,并在它的命名空间里执行一段 Python 代码。

object main_module = import("__main__");
object main_namespace = main_module.attr("__dict__");
object ignored = exec("hello = file('hello.txt', 'w')\n"
    "hello.write('Hello world!')\n"
    "hello.close()",
    main_namespace);

这段代码会在当前目录创建一个叫 hello.txt 的文件,里面写着那句编程圈无人不晓的问候语。

操纵 Python 对象

很多时候我们需要一个类来直接操作 Python 对象。其实上一节已经见过了——那个名字很直白的 object 类(以及它的派生类)。它们可以用 handle 来构造。下面这个例子应该能让你更清楚:

object main_module = import("__main__");
object main_namespace = main_module.attr("__dict__");
object ignored = exec("result = 5 ** 2", main_namespace);
int five_squared = extract(main_namespace["result"]);

这里先获得 __main__ 模块的命名空间字典,然后把 5 ** 2 的结果赋给变量 result,最后从字典中读出并提取成整数。当然,更简单的做法是用 eval

object result = eval("5 ** 2");
int five_squared = extract(result);

异常处理

如果在执行 Python 表达式时发生了异常,Boost.Python 会抛出 error_already_set 异常:

try
{
    object result = eval("5/0");
    // 执行永远不会到这一行:
    int five_divided_by_zero = extract(result);
}
catch(error_already_set const &)
{
    // 用某种方式处理异常
}

error_already_set 异常类本身不包含任何信息。想了解发生了什么 Python 异常,你得在 catch 块里使用 Python C API 的异常处理函数。最简单的做法是调用 PyErr_Print() 把异常回显打印到控制台,或者比较异常类型:

catch(error_already_set const &)
{
    if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError))
    {
        // 专门处理除零异常
    }
    else
    {
        // 把其他所有错误打印到 stderr
        PyErr_Print();
    }
}
来源:https://blog.csdn.net/xinqingwuji/article/details/89316266

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
Kafka与CentOS其他服务协同配置指南

Kafka与CentOS其他服务协同配置指南

Kafka在CentOS生态中作为数据流通中枢,与EFK日志收集、HDFS存储、HBase、Prometheus+Grafana监控及SparkStreaming流处理系统协同,通过生产者-消费者模式构建实时数据管道,实现解耦、削峰填谷与高效集成。

时间:2026-07-12 06:52
如何使用deluser命令重命名用户的详细操作指南

如何使用deluser命令重命名用户的详细操作指南

在Linux系统管理中,重命名用户需通过删除旧用户并创建新用户实现。操作包括备份数据、用rsync迁移文件、更改文件所有权、删除旧用户及家目录,最后重新登录验证。不同发行版命令略有差异,建议在测试环境演练。

时间:2026-07-12 06:52
详细CentOS系统中C++配置常见问题及解决方法大全

详细CentOS系统中C++配置常见问题及解决方法大全

CentOS配置C++常见问题包括编译器缺失或版本过旧、环境变量错误、依赖库开发包未装、多版本冲突、权限路径问题、内存不足及内核参数不当。需正确安装gcc-c++及devel包,配置PATH与库路径,使用devtoolset或alternatives管理版本,调整权限与ulimit、sysctl参数。

时间:2026-07-12 06:52
CentOS C++环境变量配置方法

CentOS C++环境变量配置方法

在CentOS系统配置C++编译器需设置路径和动态库路径。先验证g++是否已安装,否则使用sudoyuminstallgcc-c++安装。通过whichg++找到安装路径后,在~ bashrc中添加exportPATH=$PATH:该路径并执行source使之生效。动态库路径可用find命令查找后类似加入LD_LIBRARY_PATH。最后用g++编译测试

时间:2026-07-12 06:52
CentOS中C++配置文件位置与路径完整说明

CentOS中C++配置文件位置与路径完整说明

CentOS中C++配置文件包括系统级全局配置( etc profile、 etc bashrc)影响所有用户,用户级配置(~ bashrc)仅影响当前用户,以及第三方库路径和构建工具CMakeLists txt。这些文件共同设置环境变量、库路径及编译选项等详细参数,用于管理相关开发环境。

时间:2026-07-12 06:52
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜