借助官方的说明文档:
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
这样就可以将模块安装成功了。
参考链接: