天天看点

c编写Python模块 c编写Python模块 附

  • 目录
  • 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对应的类型转换参数表

c编写Python模块 c编写Python模块 附

图:这里写图片描述

2. Py_BuildValue的用法表

c编写Python模块 c编写Python模块 附

图:这里写图片描述