首先,編寫包含py接口的c源檔案,稱為wrap.c。這一步可以使用swig帶過。 例如:swig
-python foo.i
接着,對wrap.c進行編譯,生成XX.so。這一步可以使用 distutils帶過。如果要用 distutils的話,則需要首先編寫一個py腳本。示例:setup(name
= ‘example‘, version = ‘1.0‘, ext_modules = [Extension(‘example‘, [‘wrap.c‘,‘example.c‘])]) 注意:句子中的list不僅不要包含wrap源檔案,還要包含函數的原始源檔案
上一步的so檔案便是最終可以使用的庫檔案,把該檔案放入py的lib中或者目前目錄,即可導入c語言擴充子產品進行使用。如果之前用過swig,還要把相應的so檔案移入子產品檔案夾中并在檔案名前加上_。示例:
cp printf.so /usr/lib64/python2.7/site-packages/_printf.so
經過了之前的學習,我已經能夠順利的使用寫好的wrap檔案生成c擴充庫了。今天我決定把自己的那些函數也都編譯成擴充庫。雖然我可以直接輕松的使用swig實作,但是swig要求必須把寫好的庫檔案放入指定目錄,否則就出問題,然而我想的是把所有需要的庫都放入一個本地目錄來友善程式的移植,swig顯然跟我的想法相悖。是以我決定自己編寫wrap檔案。
wrap檔案中有幾個關鍵函數必須掌握。首先是:PyObject* wrap_fact(PyObject* self, PyObject* args)。這個函數的作用是分析python傳進來的參數并執行響應的c函數。PyArg_ParseTuple(args, "is", &n,&c)函數可以用來分析python傳進來的(元組)參數。其中的字元串參數是一個格式化字元串,裡面is分别表示整形和字元串。後邊需要加上存儲參數的c變量位址,這裡需要注意的是,這些參數必須是用來存儲參數的變量的位址,即使要存儲的是一個字元串也一樣,這點·跟scanf還是有一定差異的。分析完參數之後,就可以直接利用得到的這些參數調用相應的c函數。之後可以利用return
Py_BuildValue("i", result)向python傳回值。示意中語句可以将result變量的值以整形傳回。總的來說,這個函數的實際作用就是取得python調用相應函數時所傳遞的參數,然後利用這些參數執行這個函數中的c代碼段,然後将c代碼段中的指定值傳回給python。
然是是一個指針數組:static PyMethodDef exampleMethods[]。這個數組用來存儲c函數映射表。每個c函數都需要有一個這樣的{"fact", wrap_fact, METH_VARARGS, "Caculate N!"}數組,其中的元素依次代表python中函數的名字,接口函數位址,參數類型,函數描述。需要擴充多少個函數就要有多少個這樣的數組。
最後是子產品初始化函數:void initexample()。注意這個函數的名字是有講究的,必須是init子產品名字。裡邊需要包含語句:m = Py_InitModule("example", exampleMethods);其中的參數分别代表子產品名字、函數映射表數組。
示例:
#include
extern int sendsyslog(const char *addr,int port,int type);
extern int sendtoac2(int type);
extern int sendtoac1(int type);
extern int rarecv(int wtime,const char *if_name2);
PyObject* sendcmsg_syslog(PyObject* self, PyObject* args)
{
int port,type, result;
char *addr;
if (! PyArg_ParseTuple(args, "sii", &addr,&port,&type))
return NULL;
result = sendsyslog(addr,port,type);
return Py_BuildValue("i", result);
}
PyObject* sendcmsg_sendac1(PyObject* self, PyObject* args)
{
int type, result;
if (! PyArg_ParseTuple(args, "i", &type))
return NULL;
result = sendtoac1(type);
return Py_BuildValue("i", result);
}
static PyMethodDef sendcmsgMethods[] =
{
{"syslog", sendcmsg_syslog, METH_VARARGS, "send syslog msg!"},
{"sendac1", sendcmsg_sendac1, METH_VARARGS ,"send a q msg to client1"},
{"sendac2", sendcmsg_sendac2, METH_VARARGS ,"send a q msg to client2"},
{"rarecv", sendcmsg_rarecv, METH_VARARGS ,"detect ra msg"},
{NULL, NULL}
};
void initsendcmsg()
{
PyObject* m;
m = Py_InitModule("sendcmsg", sendcmsgMethods);
}