python总是和c连接最紧密,因为python本身就是用c写的。python用c进行扩展模块也很容易和高效。
使用c写python的模块,首先要引入Python.h头文件,并且一些数据类型和要是用Python模块中定义的,这样才能编译成python能识别的模块。
#include <Python.h> //导入头文件 /*python中都是对象,所以用c写的方法也需要返回python可以识别的对象 模块中的方法一般都是static的,第一个参数就等同于我们在python中类的self对象一样。 模块中这个一般不用手动传入,args是函数的可变参数。 Py_BuildValue函数用于把c中的数据类型转换为python的类型。 */ static PyObject* test(PyObject* self, PyObject* args) { //返回字符串helloworld return Py_BuildValue("s","helloworld"); } static PyObject* hello(PyObject* self, PyObject* args) { //返回int类型 return Py_BuildValue("i",5); } /* 模块方法数组,默认也是静态static,用于定义python模块中的方法列表 这个方法数组其实是由多个数组组成 {"test", test, METH_VARARGS, "Execute a shell command."}这个数组表示一个函数类型及其信息 "test"python模块中的函数名,test 定义在c中的函数名称, METH_VARARGS,表示函数参数类型是元组形式(还有一种形式是METH_KEYWORDS,表示python中的字典形式) "Execute a shell command."是函数注释 最有的{NULL, NULL, 0, NULL}用来结束函数信息,值无实际意义。 */ static PyMethodDef addMethods[] = { {"test", test, METH_VARARGS, "Execute a shell command."}, {"hello", hello, METH_VARARGS, "Execute a shell command."}, {NULL, NULL, 0, NULL} }; /* 模块初始化函数,必须定义为init*,*表示模块名 这个函数用于python来初始化模块函数信息 "add" 模块名,addMethods就是上面的函数信息数组 */ PyMODINIT_FUNC initadd() { Py_InitModule("add", addMethods); }
gcc -shared -O main.c -L c:\Python27\libs -lpython27 -I c:\Python27\include -o add.pyd
编译为pyd文件,然后使用python控制台访问:
import add print dir(add) print add.test() print add.hello()
输出
>>> ['__doc__', '__file__', '__name__', '__package__', 'hello', 'test'] helloworld 5 >>>
distutils模块会自动编译为一个pyd模块文件。只需要两个参数,一个模块名,一个c源文件就可以。
from distutils.core import setup, Extension
#add模块名 main.c c源文件 module1 = Extension('add', sources = ['main.c']) setup ( name = 'PackageName', version = '1.0', description = 'This is a demo package', ext_modules = [module1] )
保存为setup.py
然后命令行执行python setup.py build --compile=mingw32在window下,一般不加--compile参数,一般都提示Unable to find vcvarsall.bat错误。我是使用mingw32编译的。