c调用python第三方包_python的C扩展调用,使用原生的python-C-Api

1、在文件第一行包含python调用扩展的头文件

#include

2、用原生C写好需要调用的函数

int add_one(inta){return a + 1;

}

3、用python规定的调用方式,加一层C语言的包装,包装内容包括

a.定义一个新的静态函数,接受两个PyObject *参数,返回一个PyObject *值

b.解析第二个输入的PyObject *(通过PyArg_ParseTuple等方法),把python输入的变量变成C的变量

c.调用原生C函数

d.将调用返回的C变量,转换为PyObject*或其子类(通过PyLong_FromLong)等方法,并返回

static PyObject * py_add_one(PyObject *self, PyObject *args){intnum;if (!PyArg_ParseTuple(args, "i", &num)) returnNULL;

returnPyLong_FromLong(add_one(num));

}

4、创建一个数组,来指明python可调用这个扩展的函数。

其中"add_one",代表编译后python调用时希望使用的函数名,

py_add_one,代表调用当前C代码中的哪个函数,

METH_VARARGS,代表函数的参数传递形式,主要包括位置参数和关键字参数两种,

关于这个变量具体参考https://docs.python.org/3/extending/extending.html的1.4节。

如果希望添加新的函数,则在最后的{NULL, NULL}之前按同样格式填写新的调用信息。

static PyMethodDef Methods[] ={

{"add_one", py_add_one, METH_VARARGS},

{NULL, NULL}

};

5、创建module的信息,包括了python调用时的模块名、可调用的函数集(就是上一步定义的Methods)等信息

static struct PyModuleDef cModule ={

PyModuleDef_HEAD_INIT,

"Test",/*module name*/

"", /*module documentation, may be NULL*/

-1, /*size of per-interpreter state of the module, or -1 if the module keeps state in global variables.*/Methods

};

6、module初始化

PyMODINIT_FUNC PyInit_Test(void){ return PyModule_Create(&cModule);}

7、写一个setup.py脚本,使用distutils包作为包构建安装的工具

from distutils.core importsetup, Extension

module1= Extension('Test', sources = ['add.c'])

setup (name= 'Test',

version= '1.0',

description= 'This is a demo package',

ext_modules= [module1])

8、调用setup.py,python setup.py build可以编译代码,python setup.py install可以编译代码并直接将包放入当前python环境的包的路径以供调用。

非常需要注意的是,python 3.5版本以后,windows平台下python的C/C++扩展不再支持gcc的编译,并强制要求使用msvc进行编译

所以python setup.py build编译出来的结果无法正常使用,需使用

python setup.py build --compiler msvc

当需要安装时,则

python setup.py build --compiler msvc install

关于此情况的参考:

https://stackoverflow.com/questions/16737260/how-to-tell-distutils-to-use-gcc

https://stackoverflow.com/questions/3297254/how-to-use-mingws-gcc-compiler-when-installing-python-package-using-pip

9、测试安装好的C扩展

importTest as t

x= 1

print(t.add_one(x))

附C文件完整代码

#include

int add_one(inta){return a + 1;

}static PyObject * py_add_one(PyObject *self, PyObject *args){intnum;if (!PyArg_ParseTuple(args, "i", &num)) returnNULL;returnPyLong_FromLong(add_one(num));

}static PyMethodDef Methods[] ={

{"add_one", py_add_one, METH_VARARGS},

{NULL, NULL}

};static struct PyModuleDef cModule ={

PyModuleDef_HEAD_INIT,"Test", /*module name*/

"", /*module documentation, may be NULL*/

-1, /*size of per-interpreter state of the module, or -1 if the module keeps state in global variables.*/Methods

};

PyMODINIT_FUNC PyInit_Test(void){ return PyModule_Create(&cModule);}

https://segmentfault.com/a/1190000000479951

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值