python底层是用c写的,c本身是一个非常底层的语言,所以它做某些事情的效率肯定会比上层语言高一些。
比如有些自动化测试用的python库,会对系统的UI进行一些捕获,点击之类的操作,这必然要用到c,实际上这些库就是用c来扩展的。先用c写一些调用系统UI的接口,然后把它封装成python方法。
下面是一个简单的用C来扩展python的例子:
test.c
#include "Python.h" static PyObject *pr_getsum(PyObject *self,PyObject *args) { int n,m; if(!PyArg_ParseTuple(args,"ii",&n,&m)) return NULL; return Py_BuildValue("i",m+n); } static PyMethodDef PrMethods[]={ {"getsum",pr_getsum,METH_VARARGS,"get the sum"}, {NULL,NULL,0,NULL} }; void initpr(void) { (void) Py_InitModule("pr",PrMethods); }
上面3个部分缺一不可,主要有:
1. 导出函数:需要注意的是PyArg_ParseTuple(args,"ii",&n,&m)) 这一句,表示python要传入的参数。
"i" 表示整数,"d"表示浮点数,“s"表示字符串。
要传入2个参数就写"ii","dd","is"等,也可以用多种选择"is|ii"表示第一个参数是整数,第二个可以是字符串或整数
2. 方法列表:PyMethodDef的成员一次表示"方法名,导出函数,参数传递方式,方法描述“
3. 初始化函数:必须以init开头
然后是编写setup.py文件,与上面的test.c文件在一个目录下
from distutils.core import setup,Extension module = Extension('pr',sources=['test.c']) setup(name='pr test',version='1.0',ext_modules=[module])
然后执行命令就可以了
python setup.py build
结束后可以看到生成了一个build目录,里面会有2个文件test.o和pr.so。我们需要用到的是pr.so文件。
可以把pr.so文件放到python的site_packages目录下,或者把pr.so所在的目录添加到sys.path里,就可以在python里直接调用了
import pr print pr.getsum(2,3)
需要注意的是,在windows上运行python setup.py build的时候可能会报错error: Unable to find vcvarsall.bat 。 这个就自己在google上搜下解决方法吧,linux和mac上应该是可以直接运行的。
使用ctypes调用c语言函数
还是上面的例子,我们要求2个数的和。那么在windows上可以这样写
__declspec(dllexport) int add(int num1, int num2) { return num1 + num2; }
然后是把这个文件编译成动态链接库,这时候需要用到cl命令
cl命令需要安装visual studio,如果已经安装了请按这个方法来配置环境变量http://hi.baidu.com/xiaoma/item/94c649dc4bc5dae3795daac2
然后运行
cl -LD test.c -o test.dll
可以在当前目录下生成一个test.dll文件,这个就是我们要用的。
然后在python文件里就可以直接使用了
from ctypes import * def main(): libtest = cdll.LoadLibrary('test.dll') print libtest.add(2,3) if __name__ == '__main__': main()
这个方法在macos x上貌似不行,有待考究