C++混合编程

Python调用C++

什么时候需要在python中调用C/C++的库呢?有什么好处呢?

  1. 复用代码:想在python中使用一个用C/C++编写的大型的、经过测试的稳定的库。
  2. 性能提升:加速python项目中的性能瓶颈部分,将瓶颈部分剥离出来,用C/C++封装成一个可以给python调用的模块,以实现加速。
  3. 测试:用python测试工具测试C/C++库

Python C-API

python 提供了 Python.h 头文件,能够将 c 或 c++ 代码封装成 可供 python 引入的动态链接库。

这一部分可以参考

Pybind11 实现 Python 与 C++ 混合编程 | Wokron's Blog

1. Extending Python with C or C++ — Python 3.12.4 documentation

Boost.Python

相比于原始的C-API,Boost.Python提供了将 C++ 代码导出为 Python 模块的工具和框架。Boost.Python 简化了通过 C++ 将现有库封装为 Python 模块的过程,而不需要直接操作 Python/C API。

这里给出在Linux下使用Boost.Python的简易demo,Linux开发环境的搭建参考我之前写的一篇博客

基于VSCode+Clangd+lldb搭建Linux C++环境_clangd lldb安装在ubuntu22下-优快云博客

然后安装g++, cmake, Boost.Python和python-dev

sudo apt update && sudo apt install g++ cmake libboost-python-dev python3-dev

编写example:

#define BOOST_PYTHON_STATIC_LIB

#include <boost/python.hpp>
#include <iostream>

struct StructionData
{
    void hello()
    {
        std::cout << "hello, this is boost::python sample!" << std::endl;
    }
    void printmsg()
    {
        std::cout << "print message done!" << std::endl;
    }
};

BOOST_PYTHON_MODULE(struct)
{
    boost::python::class_<StructionData>("StructionData")
        .def("hello", &StructionData::hello)
        .def("printmsg", &StructionData::printmsg);
}

编译链接后导出为struct.so,然后在Python中导入使用
请添加图片描述

上面的demo参考自up主的教学视频

C++和Python混合编程第二期:C++数据类型的导出和调用(上)_哔哩哔哩_bilibili

我照着up的教程写了一些demo,代码在snippet/boost_python at main · hwg1999/snippet (github.com)

这里根据up主的教程总结下 Boost.Python中用于导出各种数据类型的接口

  • 函数:boost::python::def()
  • 常量:boost::python::scope().attr
  • 枚举:boost::python::enum_<T>("TName")
  • 结构体/默认构造函数:boost::python::class_<T>("TName")
  • 自定义构造函数:boost::python::class_<T>("TName", boost::python::init<para>())
  • 成员变量:def_readonly()/def_readwrite()
  • 属性:add_property()
  • 继承类:boost::python::class_<T, boost::python::bases<TBase>>("TName"))
  • 虚函数:boost::python::wrapperboost::python::class_<TBase, boost::noncopyable>
  • 纯虚函数:boost::python::wrapperboost::python::class_<TBase, boost::noncopyable>boost::python::pure_virtual
  • 运算符:def(boost::python::self + boost::python::self)
  • 重载函数:需要重载声明
  • 类成员函数的默认参数:boost::python::optionalBOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
  • 自由函数的默认参数:BOOST_PYTHON_FUNCTION_OVERLOADS
  • 智能指针:boost::python::register_ptr_to_python<TP>()
  • 返回值为引用的函数:boost::python::return_value_policy<boost::python::reference_existing_object>()
  • 返回值为静态对象的函数:boost::python::return_value_policy<boost::python::reference_existing_object>()
  • 返回值为新对象的函数:boost::python::return_value_policy<boost::python::manage_new_object>()

一些参考资料:

JasonLiThirty - 简书 (jianshu.com)

Boost.Python - 1.85.0

Boost.Python Reference Manual - 1.85.0

其他方法

除了上面提到的两种方法,还有一些其他工具可以将C/C++代码导出为Python模块,比如SWIG、CPython和pybind11等等,可参见

一文总结Python和C/C++的交互方式 - 海滨的Blog (hbblog.cn)

Python Bindings: Calling C or C++ From Python – Real Python

How to Call C++ from Python (matecdev.com)

Python 绑定:从 Python 调用 C 或 C++ - 开发者之家 - SegmentFault 思否


C++调用Python

为什么需要在C++中执行Python代码?

  1. 灵活性:当一个C++项目中有部分功能预期将会经常变更需求,期望获得更高的灵活性(比如热更新?)时,将这部分功能用Python实现,在C++中进行调用。
  2. 插件系统:程序中的某个部分的功能设计成插件,插件支持Python编写的话,用户就可以通过编写Python代码来扩展功能
  3. 快速原型开发:Python具有简洁明了的语法和丰富的标准库,可以快速开发原型。通过C/C++调用Python可以充分利用Python的优势,快速构建原型,并在性能方面进行优化
  4. 与Python生态系统的互操作性: Python具有庞大的生态系统,拥有丰富的第三方库和模块。通过C/C++调用Python,可以与这些库和模块进行无缝的互操作,利用Python生态系统的力量。

c++ 调用 python ,本质上是在 c++ 中启动了一个 python 解释器,由解释器对 python 相关的代码进行执行,执行完毕后释放资源,达到调用目的。

从操作步骤上看,C++调用Python低层接口可以分为几个阶段:

  • 初始化Python解释器
  • 从C++到Python转换数据
  • 用转换后的数据做参数调用Python函数
  • 把函数返回值转换为C++数据结构

下面是一个简易的demo:

#include <Python.h>

int main(int argc, char* argv[])
{
    Py_Initialize();
    PyRun_SimpleString("print('Hello Python!')\n");
    Py_Finalize();
    return 0;
}

执行结果:
在这里插入图片描述

更多用法可参考

1. Extending Python with C or C++ — Python 3.12.4 documentation

所有参考资料

(99+ 封私信 / 80 条消息) C++和python的代码如何相互调用? - 知乎 (zhihu.com)

(99+ 封私信 / 80 条消息) 如何实现 C/C++ 与 Python 的通信? - 知乎 (zhihu.com)

(99+ 封私信 / 80 条消息) 在什么场景下,你们会使用C/C++调用python? - 知乎 (zhihu.com)


Python实例浅谈之三Python与C/C++相互调用 - CalvinChu - 博客园 (cnblogs.com)

《深度剖析CPython解释器》31. Python 和 C / C++ 联合编程 - 古明地盆 - 博客园 (cnblogs.com)

python调用C\C 的方法各有什么优势,哪个最好 – PingCode

1. Extending Python with C or C++ — Python 3.12.4 documentation

C++调用Python(混合编程)函数整理总结 - DoubleLi - 博客园 (cnblogs.com)


Boost(2):boost.python库介绍及简单示例-优快云博客

C++和Python混合编程第二期:C++数据类型的导出和调用(上)_哔哩哔哩_bilibili

C++和Python的混合编程-C++数据类型的导出和调用 - 简书 (jianshu.com)

Boost.Python - 1.85.0

Boost.Python Reference Manual - 1.85.0

PY++ 自动将你的C++程序接口封装供python调用 - 阁子 - 博客园 (cnblogs.com)


1. Extending Python with C or C++ — Python 3.12.4 documentation

Pybind11 实现 Python 与 C++ 混合编程 | Wokron's Blog

一文总结Python和C/C++的交互方式 - 海滨的Blog (hbblog.cn)

Python Bindings: Calling C or C++ From Python – Real Python

Python 绑定:从 Python 调用 C 或 C++ - 开发者之家 - SegmentFault 思否

How to Call C++ from Python (matecdev.com)

《深度剖析CPython解释器》31. Python 和 C / C++ 联合编程 - 古明地盆 - 博客园 (cnblogs.com)


Python 的混合模式调试 - Visual Studio (Windows) | Microsoft Learn

《Cython系列》1. Cython 是什么?为什么要有 Cython?为什么我们要用 Cython? - 古明地盆 - 博客园 (cnblogs.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值