- 目录
- c编写Python模块
- 1. 利用样板来包装函数
- 2. 为每个模块增加PyMethodDef ModuleMethods[]数组
- 3. 编写初始化函数
- 4. 总览
- 5. 编写用于编译安装的脚本
- 6. 编译安装:
- 7. 使用:
- 附
- 1. python和c对应的类型转换参数表
- 2. Py_BuildValue的用法表
c编写Python模块
为何要编写C扩展 保护核心代码 解决性能瓶颈 创建C一些特有的东西 环境: Linux .13.9-300.fc27.x86_64 Python 3.6.3 开始 目标 这次我么来实习制作Python3的扩展,实现两个功能:
求一个整数的绝对值 求一个字符串的逆序 用c实现这个功能:
int my_abs(int n){
if(n<)
n = n * ;
return n;
}
void my_reverse(char *s){
if(s){
int len = strlen(s);
int i;
char t;
for(int i= ;i<(len)/;i++){
t = s[i];
s[i] = s[len-i];
s[len-i] = t;
}
}
}
1. 利用样板来包装函数
//作用,接受python传的值,将结果计算后转为Python对象返回给python
//返回类型PyObject*,函数名:模块名_函数名
static PyObject *Extest_abs(PyObject *self,PyObject *args){
int num;
if(!(PyArg_ParseTuple(args,"i",&num))){ //获取Python传递的参数
return NULL;
}
return (PyObject*)Py_BuildValue("i",my_abs(num));//将结果转换为Python类型并返回
}
static PyObject *Extest_reverse(PyObject *self,PyObject *args){
char *s;
if(!(PyArg_ParseTuple(args,"z",&s))){
return NULL;
}
my_reverse(s);
return (PyObject*)Py_BuildValue("s",s);
}
2. 为每个模块增加PyMethodDef ModuleMethods[]数组
static PyMethodDef ExtestMethods[] = {
{"abs",Extest_abs,METH_VARARGS},//函数名,包装函数名,解析
{"reverse",Extest_reverse,METH_VARARGS},
{NULL,NULL},//作为结束
};
3. 编写初始化函数
static struct PyModuleDef ExtestModule = {
PyModuleDef_HEAD_INIT,//默认
"Extest",//模块名
NULL,
,
ExtestMethods //上面的数组
};
void PyInit_Extest(){
PyModule_Create(&ExtestModule);
}
4. 总览
my_extend.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<Python.h>
int my_abs(int n){
if(n<)
n = n * ;
return n;
}
void my_reverse(char *s){
if(s){
int len = strlen(s);
int i;
char t;
for(i= ;i<(len)/;i++){
t = s[i];
s[i] = s[len-i];
s[len-i] = t;
}
}
}
void test(void){
printf("test my_abs:\n");
printf("|-8590|=%d\n",my_abs());
printf("|-0|=%d\n",my_abs());
printf("|5690|=%d\n",my_abs());
printf("test my_reverse:\n");
char s0[] = "apple";
char s1[] = "I love you!";
char *s2 = NULL;
my_reverse(s0);
my_reverse(s1);
my_reverse(s2);
printf("'apple' reverse is '%s'\n",s0);
printf("'I love you!' reverse is '%s'\n",s1);
printf("null reverse is %s\n",s2);
}
//作用,接受python传的值,将结果计算后转为Python对象返回给python
//返回类型PyObject*,函数名:模块名_函数名
static PyObject *Extest_abs(PyObject *self,PyObject *args){
int num;
if(!(PyArg_ParseTuple(args,"i",&num))){
return NULL;
}
return (PyObject*)Py_BuildValue("i",my_abs(num));
}
static PyObject *Extest_reverse(PyObject *self,PyObject *args){
char *s;
if(!(PyArg_ParseTuple(args,"z",&s))){
return NULL;
}
my_reverse(s);
return (PyObject*)Py_BuildValue("s",s);
}
static PyObject *Extest_test(PyObject *self,PyObject *args){
test();
return (PyObject*)Py_BuildValue("");
}
//为每个模块增加PyMethodDef ModuleMethods[]数组
static PyMethodDef ExtestMethods[] = {
{"abs",Extest_abs,METH_VARARGS},
{"reverse",Extest_reverse,METH_VARARGS},
{"test",Extest_test,METH_VARARGS},
{NULL,NULL},
};
static struct PyModuleDef ExtestModule = {
PyModuleDef_HEAD_INIT,
"Extest",
NULL,
,
ExtestMethods
};
void PyInit_Extest(){
PyModule_Create(&ExtestModule);
}
5. 编写用于编译安装的脚本
setup.py
from distutils.core import setup,Extension
MOD = 'Extest' #模块名
setup(name=MOD,ext_modules=[Extension(MOD,sources=['my_extend.c'])]) #源文件名
6. 编译安装:
python3 setup.py build #提示没有Python.h百度
python3 setup.py install
7. 使用:
>>> import Extest
>>> Extest.test()
test my_abs:
||=
||=
||=
test my_reverse:
'apple' reverse is 'elppa'
'I love you!' reverse is '!uoy evol I'
null reverse is (null)
>>> Extest.abs()
>>> Extest.reverse("abc")
'cba'
附
1. python和c对应的类型转换参数表

图:这里写图片描述
2. Py_BuildValue的用法表
图:这里写图片描述