使用Boost.Python库实现C++与Python相互调用的详细步骤与指南
Boost Python简化了C++扩展Python模块的开发,封装了引用计数与类型转换。通过handle和call_method,可便捷地嵌入Python模块、调用函数及操作类对象。支持使用BOOST_PYTHON_MODULE导出C++函数供Python调用,但需手动添加模块路径并调用初始化函数。
Boost.Python是Boost库家族中一个非常实用的组件,旨在帮助C++开发者更便捷地为Python编写扩展模块。坦白说,以往使用纯Python C API编写扩展相当繁琐,涉及大量引用计数和类型转换,稍有不慎就会导致内存泄漏。Boost.Python将这些复杂细节封装起来,显著提升了开发效率。目前,它对将Python嵌入C++的支持尚不全面,但仅其提供的工具集就已经能节省大量时间。此外,华宇煜编写的《Boost.Python简明教程》内容扎实,可作为补充阅读材料。
1 Boost.Python 安装简介
在正式开始编写代码之前,需要先编译Boost库。首先从Boost官网下载源码包,并将其解压到合适的目录。需要注意的是,在安装Boost.Python之前,请确保Python已正确安装,这是必要的前提条件。
1.1 Linux 下的编译
首先进入Boost源码目录,运行 ./configure 脚本。配置时需要传递Python相关参数,例如Python解释器路径、版本号和根目录:
./configure --with-python=/usr/bin/python --with-python-version=2.4 --with-python-root=/usr
随后,如同大多数Linux程序一样,执行 make 开始编译。编译完成后,切换到root权限并运行 make install,Boost的头文件和库文件将自动复制到系统指定目录,之后即可直接使用。
1.2 使用 MinGW + MSys 在 Windows 下的编译
在Windows环境下,编译步骤稍多一些。首先需要编译Boost自带的构建工具bjam。进入Boost源码目录下的 tools/build/jam_src,执行 build.bat mingw,稍等片刻即可获得bjam.exe。将其放置于 %PATH% 可访问的目录中,例如 C:\Windows\System32,或自行创建一个工具目录并添加到环境变量。
然后返回Boost源码根目录,运行bjam进行编译。需要指定Python相关变量:PYTHON_ROOT 指向Python安装目录(例如 E:\Python),PYTHON_VERSION 填入版本号(例如 2.4)。具体命令如下:
bjam.exe "-sTOOLS=mingw" "-sPYTHON_ROOT=E:\Python" "-sPYTHON_VERSION=2.4"
编译完成后,头文件和库文件默认存放在 C:\Boost 目录下,您可以根据需要将其移动到其他位置备用。
2 使用 Boost.Python 将 Python 模块嵌入 C++
Boost.Python目前尚未提供完整的Python嵌入C++的封装库,因此许多底层操作仍需借助Python C API来完成。然而,借助Boost.Python提供的几个工具模块,至少可以在很大程度上简化繁琐的引用计数和类型转换工作。
2.1 修改模块加载路径,装入 Python 模块
与所有嵌入Python的C/C++程序相同,第一步是在第一个 #include 之前引入 Python.h,然后在程序开始时调用 Py_Initialize(),在程序结束时调用 Py_Finalize()。
接下来需要准备加载Python模块。为了使Python解释器能够找到模块文件,需要将模块所在路径添加到搜索路径中。对应的Python语句大致如下:
import sys
if not '/module/path' in sys.path:
sys.path.append('/module/path')
使用Python C API执行类似的代码即可。路径添加完成后,通过 PyImport_ImportModule 函数加载模块,该函数返回一个 PyObject * 指针。为避免手动处理引用计数的麻烦,可以使用Boost.Python提供的 handle 来包装该指针:
#include
...
boost::python::handle<>* _module; // Module handle.
std::string path; // Path of the Python module.
std::string module; // Module name.
...
try
{
PyRun_SimpleString("import sys");
PyRun_SimpleString((std::string("if not '") + path
+ "' in sys.path: sys.path.append('" + path + "')").c_str());
_module = new boost::python::handle<>(
PyImport_ImportModule((char *) module));
...
}
catch (...)
{
PyErr_Print();
PyErr_Clear();
delete _module;
_module = NULL;
return false;
}
...
需要特别注意的是:通过Python C API初始化后的解释器不会自动将当前目录加入搜索路径。因此,即使Python模块位于当前目录,也必须使用上述代码手动添加当前路径,否则 PyImport_ImportModule 将无法找到模块。
当Python模块使用完毕或程序退出时,务必使用 delete 释放 _module 指针。handle 在释放时会自动处理底层的Python模块引用计数和资源回收。
2.2 调用 Python 函数
导入模块后,调用Python函数变得非常便捷。Boost.Python提供了一个实用的模板函数 boost::python::call_method,它封装了调用过程中的所有细节:无需手动将C++参数打包成 PyObject *、构造元组、传递参数以及解包返回值。只需如下编写:
boost::python::call_method<返回值类型>(模块指针, "Python 函数名",
参数 1, 参数 2, ...);
模块指针可以通过之前提到的 _module 对象的 get() 方法获取,例如:
...
bool result;
std::string config_file;
...
try
{
return boost::python::call_method(_module->get(), "initialize",
config_file);
}
catch (...)
{
PyErr_Print();
PyErr_Clear();
...
}
...
2.3 使用 Python 类对象
通过Python C API调用Python类对象与调用普通函数的思路基本相同。只需调用类的构造方法获得一个对象,然后将该对象的指针视为模块指针,用相同的方式调用其成员方法。以下代码演示了如何从 _module 创建一个 YukiSession 对象、构造一个Python列表、调用其成员方法,以及从列表中提取元素:
...
boost::python::handle<> _yukisession;
...
// Retrieve the module handle and namespace handle.
boost::python::object main_module(*_module);
boost::python::object main_namespace = main_module.attr("__dict__");
// Call the method and get the object handle.
_yukisession = boost::python::handle<>((PyRun_String(
"YukiSession()", Py_eval_input,
main_namespace.ptr(), main_namespace.ptr())));
...
// Compose a list.
boost::python::list param;
param.append(boost::python::str(_addr.get_host_addr()));
param.append(boost::python::str());
// Call the method and retrieve the result.
// Method is equivalent to:
// "bool __thiscall YukiSession::on_welcome(list param);"
result = boost::python::call_method
(_yukisession.get(), "on_welcome", param);
// Extract an item from a list.
str = boost::python::call_method
(param.ptr(), "__getitem__", 1);
...
3 在嵌入的 Python 模块中调用 C++ 程序
通过动态链接库方式使用Boost.Python将C++模块导出到Python,与直接在C++可执行程序中导出模块供嵌入的Python解释器使用,编写方式几乎完全相同。此处仅简要介绍导出普通函数的方法。如需了解导出C++类、导出可被Python重载的类等高级功能,建议参考华宇煜的《Boost.Python简明教程》或官方文档。
3.1 导出 C++ 函数
使用 BOOST_PYTHON_MODULE 宏定义要导出的Python模块,然后在宏内部使用 boost::python::def 声明导出的函数、参数名和文档字符串。例如,下面的例子导出了C++函数 yukigettext,并在Python中将其重命名为 gettext:
const char *yukigettext(const char *id);
BOOST_PYTHON_MODULE(yuki)
{
boost::python::def("gettext", yukigettext,
boost::python::args("id"), "Translate message.");
}
3.2 为 Python 初始化 C++ 模块
使用 BOOST_PYTHON_MODULE(name) 宏后,会自动生成一个名为 initname 的函数。我们需要在 Py_Initialize() 之后调用该函数来初始化导出的模块。例如,刚才导出的模块名为 yuki,则初始化时调用 inityuki():
...
Py_Initialize();
inityuki();
...
3.3 在 Python 模块中调用 C++ 模块
现在,在Python代码中就可以像导入普通模块一样导入该C++模块,并直接调用其中的函数:
import yuki
...
print yuki.gettext("This is a test!")
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
Kafka与CentOS其他服务协同配置指南
Kafka在CentOS生态中作为数据流通中枢,与EFK日志收集、HDFS存储、HBase、Prometheus+Grafana监控及SparkStreaming流处理系统协同,通过生产者-消费者模式构建实时数据管道,实现解耦、削峰填谷与高效集成。
如何使用deluser命令重命名用户的详细操作指南
在Linux系统管理中,重命名用户需通过删除旧用户并创建新用户实现。操作包括备份数据、用rsync迁移文件、更改文件所有权、删除旧用户及家目录,最后重新登录验证。不同发行版命令略有差异,建议在测试环境演练。
详细CentOS系统中C++配置常见问题及解决方法大全
CentOS配置C++常见问题包括编译器缺失或版本过旧、环境变量错误、依赖库开发包未装、多版本冲突、权限路径问题、内存不足及内核参数不当。需正确安装gcc-c++及devel包,配置PATH与库路径,使用devtoolset或alternatives管理版本,调整权限与ulimit、sysctl参数。
CentOS C++环境变量配置方法
在CentOS系统配置C++编译器需设置路径和动态库路径。先验证g++是否已安装,否则使用sudoyuminstallgcc-c++安装。通过whichg++找到安装路径后,在~ bashrc中添加exportPATH=$PATH:该路径并执行source使之生效。动态库路径可用find命令查找后类似加入LD_LIBRARY_PATH。最后用g++编译测试
CentOS中C++配置文件位置与路径完整说明
CentOS中C++配置文件包括系统级全局配置( etc profile、 etc bashrc)影响所有用户,用户级配置(~ bashrc)仅影响当前用户,以及第三方库路径和构建工具CMakeLists txt。这些文件共同设置环境变量、库路径及编译选项等详细参数,用于管理相关开发环境。
- 热门数据榜
相关攻略
2026-07-12 06:52
2026-07-12 06:52
2026-07-12 06:52
2026-07-12 06:52
2026-07-12 06:52
2026-07-12 06:51
2026-07-12 06:51
2026-07-12 06:51
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

