用C給python寫module的步驟(入門)

顧名思義,就是用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')

 

參考博客:

https://blog.csdn.net/xiaozoom/article/details/83097136

https://www.jianshu.com/p/29d45124f54a

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章