Python的很多库中都包含了C/C++的代码,在安装这种库的时候,尝尝会遇到这样的报错:
error: unable to find vcvarsall.bat
通常的解决方案有两种:
安装visual studio或者mingw;
使用编译好的Python库文件,进行安装。
一般大家都会选择安装编译过的库文件,或者安装mingw,但是如果要在Windows下为自己的Python程序编写扩展,安装visual studio是最优的解决方案。
下面介绍使用C++编写Python扩展模块的常见写法。
传入有限个数据
先建立一个Exten.cpp文件,编写如下代码:
#include "Python.h"// 函数主体int add(int a,int b) { return a + b; }// 包裹函数static PyObject *Exten_add(PyObject *self,PyObject *args) { int a,b; // 获取数据,i代表int,ii代表两个int // 如果没有获取到,则返回NULL if (!PyArg_ParseTuple(args,"ii",&a,&b)) { return NULL; } return (PyObject*)Py_BuildValue("i",add(a,b)); }// 添加PyMethodDef ModuleMethods[]数组static PyMethodDef ExtenMethods[] = { // add:可用于Python调用的函数名,Exten_add:C++中对应的函数名 {"add",Exten_add,METH_VARARGS}, {NULL,NULL}, };// 初始化函数static struct PyModuleDef ExtenModule = { PyModuleDef_HEAD_INIT, "Exten",//模块名称 NULL, -1, ExtenMethods };void PyInit_Exten() { PyModule_Create(&ExtenModule); }
再在同文件夹下建立setup.py文件,编写如下代码:
from distutils.core import setup,Extension MOD = 'Exten' #模块名setup(name=MOD,ext_modules=[Extension(MOD,sources=['D:\\Exten.cpp'])])
然后在CMD控制台输入:
python D:\\setup.py build python D:\\setup.py install
此模块便已经安装成功了。可以直接在Python代码中调用:
>>> import Exten>>> Exten.add(1,3)4
传入可迭代对象
这种方式只能处理单个数据传入的任务,如果需要处理批量数组等批量数据,则需要涉及到Python对象到C++对象的转化。
以max函数为例,添加max函数之后,还需要为max编写包裹函数,整个Exten文件中代码如下:
#include "Python.h"#include <vector>#define INT_MIN -2147483648using namespace std;// 函数主体int add(int a,int b) { return a + b; }int max(vector<int> lst) { int max_num = INT_MIN; for (int i =0; i< lst.size(); i++) { if (lst[i] > max_num) { max_num = lst[i]; } } return max_num; }// 包裹函数static PyObject *Exten_add(PyObject *self,PyObject *args) { int a,b; // 如果没有获取到数据 if (!PyArg_ParseTuple(args,"ii",&a,&b)) { return NULL; } return (PyObject*)Py_BuildValue("i",add(a,b)); }// 模块中每个可供Python调用的函数都需要一个对应的包裹函数static PyObject *Exten_max(PyObject *self,PyObject *args) { PyObject *obj; vector<int> lst; // O代表对象 if (!PyArg_ParseTuple(args,"O",&obj)) { return NULL; } // 获取可迭代对象 PyObject *iter = PyObject_GetIter(obj); if (!iter) { PyErr_SetString(PyExc_TypeError,"The object is not iterable!"); return NULL; } while (true) { // 逐个获取列表中的各个元素 PyObject *next = PyIter_Next(iter); if (!next) { break; } // 检查是否为long或者long的子类(包括int) if (!PyLong_Check(next)) { PyErr_SetString(PyExc_TypeError,"Int or Long list is expected!"); return NULL; } // 由Python的Long转化为C/C++的long long num = PyLong_AsLong(next); lst.push_back(num); } return (PyObject*)Py_BuildValue("i",max(lst)); }// 添加PyMethodDef ModuleMethods[]数组static PyMethodDef ExtenMethods[] = { // add:可用于Python调用的函数名,Exten_add:C++中对应的函数名 {"add",Exten_add,METH_VARARGS}, {"max",Exten_max,METH_VARARGS}, {NULL,NULL}, };// 初始化函数static struct PyModuleDef ExtenModule = { PyModuleDef_HEAD_INIT, "Exten",//模块名称 NULL, -1, ExtenMethods };void PyInit_Exten() { PyModule_Create(&ExtenModule); }
采取同样的方式build + install之后,就可以使用了:
>>> import Exten>>> Exten.max([1,2,3,4])4>>> Exten.max([1,2,3,4.1]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Int or Long list is expected!
作者:dalalaa
链接:https://www.jianshu.com/p/eb2618067eae
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦