- 安装C++中的python扩展模块
- 使用C++编写python模块
- STL适配扩展
- 类适配扩展
- 参考文献
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,其宏原型如下:
PYBIND11_MODULE(module_name,module); // 定义Python模块
一个简单的例子如下,其定义了一个C++函数info,其会打印C++的环境信息。然后我们将其添加到pybind11之中。另外再定义一个有参的函数add,其计算两数之和。
#includenamespace 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 3STL适配扩展
pybind11也支持函数的参数和返回值使用标准容器,会自动转换成python中的list和dict。不过需要包含头文件stl.h下面是一个例子:
#include#include #include 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 tu) { get<0>(tu)++; get<1>(tu)++; get<2>(tu) += "?"; return tu; }); module.def("use_list", [](vector &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_。下面是个例子:
#includenamespace 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_ (m, "Point") .def(py::init()) .def(py::init ()) .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条)