C++、Python混合编程

安装C++中的python扩展模块

Python本身有着C接口,可以用C语言编写扩展模块,提供这个扩展的就是pybind11,有了它我们就能使用C++来开发Python扩展了。

首先我们需要在centos环境下安装这个库,使用以下命令:

sudo yum -y install python3-devel
sudo yum -y install python3-pip
pip3 install pytest
pip3 install pybind11

ubuntu环境下使用以下命令:

sudo apt-get install python3-dev
sudo apt-get install python3-pip
pip3 install pytest
pip3 install pybind11

使用C++编写python模块

在C++中,只需要使用一个宏PYBIND11_MODULE,其宏原型如下:

/**
 * @brief python 扩展模块
 * moudle_name 扩展名称,可以使用python语法import导入
 * module python::module实例对象,封装了所有操作
 */
PYBIND11_MODULE(module_name,module); // 定义Python模块

一个简单的例子如下,其定义了一个C++函数info,其会打印C++的环境信息。然后我们将其添加到pybind11之中。另外再定义一个有参的函数add,其计算两数之和。

#include <pybind11/pybind11.h>

namespace py = pybind11; // 名字空间别名,简化代码

PYBIND11_MODULE(pydemo, m) // 定义Python模块pydemo
{
    m.def("info", // 定义Python函数
          []()    // 定义一个lambda表达式
          {
              py::print("c++ version =", __cplusplus); // pybind11自己的打印函数
              py::print("gcc version =", __VERSION__);
              py::print("libstdc++   =", __GLIBCXX__);
          });
    m.def("add",           // 定义Python函数
          [](int a, int b) // 有参数的lambda表达式
          {
              return a + b;
          });
} // Python模块定义结束

之后,我们使用如下代码进行编译:

g++ main.cpp -std=c++11 -shared -fPIC  `python3 -m pybind11 --includes` -o pydemo`python3-config --extension-suffix`

这个编译代码较为复杂,我们来解释以下:

# 最后" "编译出来的文件"`python3-xxxxxxxx  "不要有空格,这个是规约,要不python找不到扩展
gcc "需要编译的文件" -std=c++11 -shared -fPIC  `python3 -m pybind11 --includes` -o "编译出来的文件"`python3-config --extension-suffix`

最后,我们编写如下的python脚本:

import pydemo

pydemo.info()
x=pydemo.add(1,2)
print(x)

测试结果如下:

[ik@localhost test]$ python3 test.py 
c++ version = 201103
gcc version = 7.5.0
libstdc++   = 20191114
3

STL适配扩展

pybind11也支持函数的参数和返回值使用标准容器,会自动转换成python中的list和dict。不过需要包含头文件stl.h下面是一个例子:

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <string>
using namespace std;

namespace py = pybind11;

PYBIND11_MODULE(pydemo,module)
{
    module.def("use_str",
               [](const string &str)
               {
                   py::print(str);
                   return str + "!";
               });
    module.def("use_tuple",
               [](tuple<int, int, string> tu)
               {
                   get<0>(tu)++;
                   get<1>(tu)++;
                   get<2>(tu) += "?";
                   return tu;
               });
    module.def("use_list",
               [](vector<int> &vec)
               {
                   py::print("input: ", vec);
                   vec.push_back(100);
                   return vec;
               });
}

python直接调用C++写好的函数就可以了:

import pydemo

list_=[0,1,2,3]
# use_list 传入list被转换成vector
ret_list = pydemo.use_list(list_)
print("ret list: "+str(ret_list))

str_="hello world"
ret_str = pydemo.use_str(str_)
print("ret str: "+ret_str)

tuple_=(0,1,"hello")
ret_tuple=pydemo.use_tuple(tuple_)
print("ret tuple: "+str(ret_tuple))

结果如下:

[ik@localhost test]$ python3 test.py
input:  [0, 1, 2, 3]
ret list: [0, 1, 2, 3, 100]
hello world
ret str: hello world!
ret tuple: (1, 2, 'hello?')

类适配扩展

C++中的类也可以等价转换到Python中进行调用,这需要用到一个特别的模板类class_。下面是个例子:

#include <pybind11/pybind11.h>

namespace py = pybind11;
class Point final
{
public:
    Point(int a)
    {
        x = a;
    }
    Point()
    {
        Point(0);
    }

public:
    int get() { return x; }
    void set(int a)
    {
        x = a;
    }

private:
    int x;
};

PYBIND11_MODULE(pydemo, m)
{
    py::class_<Point>(m, "Point")
        .def(py::init())
        .def(py::init<int>())
        .def("get", &Point::get)
        .def("set", &Point::set);
};

python中直接调用就可以了:

import pydemo

point = pydemo.Point(1);
print(point.get())

最终输出结果如下:

[ik@localhost test]$ python3 test.py
1

参考文献

[1] 罗剑锋.罗剑锋的C++实战笔记.极客时间

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Qt是一个跨平台的应用程序开发框架,常用于C++开发Python是一种动态类型的脚本语言混合编程指的是在一个项目中同时使用Qt/C++Python进行开发混合编程的好处是可以充分发挥Qt和Python各自的优势。Qt/C++可以提供高性能和可靠性,适用于底层开发和系统级编程Python则提供了简洁易懂、高效编程以及大量的第三方库,适用于快速开发和原型设计。 混合编程的打包过程可以分为以下几个步骤: 首先,需要安装相应的编译工具和开发环境,如Qt、C++编译器和Python解释器。确定使用的Qt版本与Python版本兼容。 其次,需要为C++部分编写Qt代码,并将其编译成dll或so动态链接库,以供Python调用。这需要使用Qt提供的相关工具和库进行编译和链接。 然后,使用Python的相关库(如PyQt或PySide)来调用C++部分的Qt代码,并将其与Python代码结合起来。这样,就可以实现Qt界面与Python逻辑的交互。 最后,将项目打包成可执行文件、二进制文件或安装包。这可以使用Qt提供的打包工具,如Qt Installer Framework,或者使用第三方工具和脚本来完成。 需要注意的是,在混合编程和打包过程中,需要仔细处理Qt的信号与槽机制与Python的回调机制之间的交互,以确保二者能够正常工作。 总之,Qt C++Python混合编程可以充分利用两者的优势,打包则需要注意兼容性和交互的处理。这种方式可以更灵活地开发应用程序,并能够适应不同的需求和平台。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shenmingik

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值