当前位置:

首页 > 编程开发 > Boost Python互调实现

Boost 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 安装简介

    在正式动手写代码之前,得先把 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 *、构造 Tuple、传递参数、解包返回值。你只需要这样写:

    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 list、调用其成员方法,以及从 list 中提取元素:

    ...
    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!")


    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Python
    相关文章 更多
    python删除一个列表里的重复元素的方法与代码示例
    python删除一个列表里的重复元素的方法与代码示例

    学习如何使用Python高效删除列表中的重复元素。本文提供5种常见方法的代码示例,涵盖保持顺序与不保持顺序的场景,适合初学者和进阶开发者参考。

    Python写接口的步骤及完整代码示例
    Python写接口的步骤及完整代码示例

    详细讲解使用Python编写Web接口的核心步骤与完整代码示例,涵盖环境准备、路由定义、数据校验、服务启动及调试测试方法。

    codex怎么读取word文档及docx文件操作教程
    codex怎么读取word文档及docx文件操作教程

    介绍如何利用编程工具读取和解析Word文档(docx格式),涵盖基础文本提取代码示例、结构化数据处理逻辑,以及处理复杂排版时的技术局限与替代方案。

    怎么在Python中调用C语言代码提升性能
    怎么在Python中调用C语言代码提升性能

    详细讲解在Python中调用C语言代码提升性能的完整实践指南,包含原理分析、编译步骤、ctypes与CFFI具体实现、性能对比及常见陷阱。

    Python与C语言的性能差异及底层原理
    Python与C语言的性能差异及底层原理

    深入解析Python与C语言在执行效率上的数量级差异,从编译机制、变量内存布局、动态类型推断到GIL锁,系统阐明底层核心原理。

    Python和C语言哪个更适合编程入门
    Python和C语言哪个更适合编程入门

    客观对比Python与C语言在心智负担、底层机制与学习反馈上的核心差异,提供清晰有据的选择标准与切实的入门学习路径。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    langgraph python guide中文入门教程详解
    langgraph python guide中文入门教程详解

    本篇LangGraph Python中文入门教程详解,系统梳理StateGraph状态机定义、节点编写、边与条件路由、检查点持久化(MemorySaver)等核心机制,提供从环境安装到完整循环智能体构建的代码示例与实操指导。

    Windows 安装 Python:从官方入口到虚拟环境的可复现实践
    Windows 安装 Python:从官方入口到虚拟环境的可复现实践

    面向后端开发者,基于 Python 官方文档说明如何在 Windows 上安装 Python、创建 venv 虚拟环境及使用 pip 管理依赖。包含可复制命令、验证方法及工具选择边界,避免常见配置误区。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。