藉助官方的說明文檔:
https://docs.python.org/2/extending/index.html
https://docs.python.org/zh-cn/3.8/extending/extending.html
我們的目標是實現一個Extend的模塊,模塊中有一個add函數,:
import Exten
print(Exten(1,2))
1.C++文件編寫
通過生成一個如下的Extend.cpp文件:
#include "Python.h"
int add(int a, int b){
return a + b;
}
/* 函數調用*/
static PyObject *Exten_add(PyObject *self, PyObject *args){
int a,b;
if(!PyArg_ParseTuple(args, "ii", &a, &b)){
return NULL;
}
//如果所有參數都具有正確的c的相應類型,並且其參數存儲在傳遞其地址的變量中。PyArg_ParseTuple>返回true
return (PyObject *)Py_BuildValue("i",add(a,b));
// "i"表示傳參類型爲int
//如果沒有返回值的話,c返回void應變成python的none,改成以下語句:
//Py_INCREF(Py_None);return Py_None;
}
/*定義調用的函數名*/
static PyMethodDef ExtenMethods[]={
{"add", Exten_add, METH_VARARGS},
{NULL, NULL}
/*{"add"是python中使用的名字,函數,METH_VARARGS是給解釋器C的標識}*/
};
static struct PyModuleDef ExtenModule = {
PyModuleDef_HEAD_INIT,
"Exten", /* m_name*/
NULL, /* m_doc*/
-1, /* m_size*/
ExtenMethods /* m_methods*/
};
/* 初始化模>塊 PyInit_name*/
PyMODINIT_FUNC
PyInit_Exten(){
PyObject *m = NULL;
m = PyModule_Create(&ExtenModule);
//m = Py_InitModule("spam", SpamMethods);
if(m == NULL)
return NULL;
}
在傳參時注意python中和C中對象的轉換。
https://docs.python.org/2/c-api/index.html
2.創建擴展模塊
使用擴展前:需要(1)編譯,(2)與Python系統鏈接
我們可以選擇兩種方法來進行擴展:
1.將 C++ 語言程序編譯成一個擴展模塊,生成擴展文件,linux下是.so,windows下是.dll,
需要指定 Python.h 頭文件所在的路徑,和鏈接 python2.7 等庫文件(-lpython2.7),例外需加上指令 -fPIC -shared 以指導其編譯成一個動態鏈接庫。編譯使用類似下面的命令(注意將其中的頭文件路徑改成你的系統中實際的路徑)
gcc -I/public/home/yinghuang/software/anaconda3/include/python3.8 -o Exten.so Exten.cpp -fPIC -shared -lpthread -ldl -lutil -lm
獲取Python.h頭文件,可以在命令行中輸入以下命令獲得:
$ python -c "import sysconfig; print( sysconfig.get_path('include') )"
2.通過Distutils在Python環境中構建和安裝模塊:
在同一目錄下建立setup.py
from distutils.core import setup,Extension
MOD = 'Exten' #模塊名
setup(name=MOD,ext_modules=[Extension(MOD,sources=['Exten.cpp'])])
在命令行中輸入:
python setup.py build
python setup.py install
這樣就可以將模塊安裝成功了。
參考鏈接: