使用C给Python写扩展
Python 扩展
Python 和 C 粘合性很好,用 C 给 Python 添加扩展一般是性能问题,另外就是想要加密部分可以编译成二进制,保证源码不会泄露。
C Extending Moudle
C 扩展大概就是使用 Python 提供的方法将 C 代码在封装一遍。Python 提供了 Python.h 头文件,使用这些接口将 C 进行包装,最后编译成 so 文件(在windows下是dll)
编写 C 扩展需要三部分,缺一不可。
- 导出函数
- 方法列表
- 初始化函数
Example
最主要的是先封装C函数,接下来举个例子,我的系统是 Ubuntu 14.04,Python2.7
定义函数
比方用 C 写一个两数相加的方法 plus,文件名为 sample.c
1 | int plus(int n, int m) |
导出函数
将该方法使用 Python 提供的API封装,首先导入头文件 Python.h
1 |
|
所有的导出函数都返回一个 PyObject 指针,如果对应的C函数没有真正的返回值(即返回值类型为void),则应返回一个全局的 None 对象(Py_None),并将其引用计数增 1
1 | PyObject* method(PyObject *self, PyObject *args) |
PyObject
是一个能表示任何Python对象的C数据类型PyArg_ParseTuple()
函数被用来将Python中的值转换成C中对应表示Py_BuildValue()
函数被用来根据C数据类型创建Python对象- 更多接口查看文档
注
PyArg_ParseTuple 更多类型请看文档, ii,表示args的长度必须为2,且必须为int类型
方法列表
1 | static PyMethodDef sampleMethods[] = { |
- 方法列表中的每项由四个部分组成:方法名、导出函数、参数传递方式和方法描述
- 方法名是从Python解释器中调用该方法时所使用的名字
- 参数传递方式则规定了Python向C函数传递参数的具体形式,可选的两种方式是METH_VARARGS和METH_KEYWORDS
- {NULL, NULL} 标识结束
初始化函数
1 | void initsample() |
构造 module 也可以使用 PyModuleDef_HEAD_INIT 和 PyModule_Create(官方这么写的)
编译链接
gcc -fpic -c -I/usr/include/python2.7 -I /usr/lib/python2.7/config-x86_64-linux-gnu sample.c gcc -shared -o sample.so sample.o cp sample.so /python/python/site-packages/
或者使用 distutils 安装