顧名思義,就是用C語言編寫核心代碼,然後封裝成PYTHON可以使用的形式,是比較常用的手段之一。
不多廢話
需要文件如下:
file1 - 包含C代碼,以及封裝樣板代碼的C文件
file2 - setup.py文件,用於編譯以及安裝
file1 -
必須 #include “Python.h”
//位置-如果裝了anaconda則在 anaconda3/include裏
//默認在/usr/local/include/python3.x/中
用C定義好函數–比如一個階乘函數,如果看懂這個函數都有難度的話…
int fac(int n){
if (n<2)
return 1;
else
return (n)*fac(n-1);
}
int main(){
…//中間部分爲測試C函數的代碼
}
然後是樣板函數,樣板代碼有幾個·組成部分:
//1.每個定義的函數都需要一個樣板函數
static PyObject* 模塊名_函數名(PyObject self,PyObject args){
//用 PyArg_ParseTuple函數解讀參數
char * command;
PyObject retval;//定義返回變量
//PyArg_ParseTuple(args,“s”,&command);
//這句話意思爲將args解讀成char類型存入command位置中
int res;
res = fac(command);//假設函數名叫fac
//用Py_BuildValue來將c變量轉換成python變量返回
//Py_BuildValue() returns a tuple
//retval = (PyObject)Py_BuildValue(類型,C變量1,C變量2)
return retval;
}
//2.方法定義-就是該module包含了哪些Methods
static PyMethodDef ExtestMethods[] = { //Extest 爲模塊名
{“fac”,Extest_fac,METH_VARARGS},
/* python中使用的名稱,對應樣板函數名稱,METH_VARARGS的意思是期待PYTHON-LEVEL的 參數*/
{“doppel”,Extest_doppel,METH_VARARGS},
{NULL,NULL} //表示函數信息結束
};
//3.模塊定義
static struct PyModuleDef extestmodule = {
PyModuleDef_HEAD_INIT,
“Extest”, //名稱
NULL, //doc
-1, //不懂
ExtestMethods //方法定義
};
//4.啓動樣板函數
PyMODINIT_FUNC
PyInit_Extest(void){ //Extest爲模塊名稱
PyObject *m;
m = PyModule_Create(&extestmodule); //爲模塊定義
if(m==NULL)
return NULL;
/可以接觸發異常等等/
return m;
}
file 2 :
#setup.py
from distutils.core import setup,Extension
MOD = ‘Extest’ //名稱
setup(name=MOD,ext_modules=[Extension(MOD,sources=[‘Extest1.c’])])//源代碼·位置
#命令
python setup.py build
python setup.py install //這個執行了之後會將編譯生成的庫複製到Python安裝目錄裏
/*
Mac-mini:c2python2 admin$ python setup.py install
running install
running build
running build_ext
running install_lib
copying build/lib.macosx-10.6-intel-3.5/Extest.cpython-35m-darwin.so -> /Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages
running install_egg_info
Writing /Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/Extest-0.0.0-py3.5.egg-info
*/
#附完整代碼
//Extest1.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Python.h"
int fac(int n){
if (n<2)
return 1;
else
return (n)*fac(n-1);
}
char *reverse(char *s){
register char t,*p=s,*q=(s+(strlen(s)-1));
while(p<q)
{
t = *p;
*p++ = *q;
*q--=t;
}
return s;
}
int main(){
char s[1024];
printf("4!==%d\n",fac(4));
printf("8!==%d\n",fac(8));
printf("12!==%d\n",fac(12));
strcpy(s,"abcdef");
printf("reversing 'abcdef', we get '%s'\n",reverse(s));
strcpy(s,"madam");
printf("reversing 'madam', we get '%s'\n",reverse(s));
return 0;
}
static PyObject * Extest_fac(PyObject *self,PyObject *args){
int num;
if(!PyArg_ParseTuple(args,"i",&num)) return NULL;
return (PyObject*)Py_BuildValue("i",fac(num));
}
static PyObject * Extest_doppel(PyObject *self,PyObject *args){
char* orig_str;
char* dup_str;
PyObject* retval;
if(!PyArg_ParseTuple(args,"s",&orig_str)) return NULL;
retval = (PyObject*)Py_BuildValue("ss",orig_str,dup_str=reverse(strdup(orig_str)));
free(dup_str);
return retval;
}
static PyMethodDef ExtestMethods[] = {
{"fac",Extest_fac,METH_VARARGS},
{"doppel",Extest_doppel,METH_VARARGS},
{NULL,NULL}
};
static struct PyModuleDef extestmodule = {
PyModuleDef_HEAD_INIT,
"Extest",
NULL,
-1,
ExtestMethods
};
PyMODINIT_FUNC
PyInit_Extest(void){
PyObject *m;
m = PyModule_Create(&extestmodule);
if(m==NULL)
return NULL;
return m;
}
#setup.py
from distutils.core import setup,Extension
MOD = 'Extest'
setup(name=MOD,ext_modules=[Extension(MOD,sources=['Extest1.c'])])
在執行了上面說的python setup.py install之後,就可以在Python代碼裏去調用了。
import Extest
if __name__ == "__main__":
n = Extest.fac(3)
print(n)
m = Extest.doppel("hello")
print(m)
// 運行結果:
// 6
// ('hello', 'olleh')
參考博客: