python创建扩展需要的3个步骤:
1、创建应用程序代码
2、利用模板包装源码
3、编译与测试
一、创建源码
递归求阶乘的函数fac()
#include<stdio.h>
int fac(int i){
if(i<2) return 1;
else return i*fac(i-1);
}
二、用模板来包装的代码
分4个步骤
1、包含Python的头文件
2、为每个模板的每一个函数增加一个形如PyObject* Module_func()的包装函数
3、为每个模板增加一个形如PyMethodDef ModuleMethos[]的数组
4、增加模块初始化函数void initModule()
补充c语言(c++)与python之间的参数传递
python到c的转换就用PyArg_Parse*()系列函数;
c到python的转换就用PyBuildValue()函数;
PyArg_Parse*()系列函数的用法跟c的sscanf()函数很像,都接受一个字符串流,并根据一个指定的格式字符串进行解析,并把结果存放在相应的指针变量上去。返回1表示解析成功,0表示解析失败。
Py_BuildValue()的用法跟sprintf()很像,把所有的参数按照格式字符串指定的格式转换一个Python对象。
Python和c/c++之间数据转换
函数 | 描述 |
---|---|
int PyArg_ParseTuple() | 把Python传过来的参数转化为c |
int PyArg_ParseTupleAndKeywords() | 与上面的功能一样,但同时支出解析关键字参数 |
PyObject* Py_BuildValue() | 把c的数据转化为Ptyhon的一个或者一组对象,并返回之 |
Python和c/c++之间数据转换的通用代码
格式代码 | Python型 | c/c++类型 |
---|---|---|
s | str | char* |
z | str/Noe | char*/NULL |
i | int | int |
l | long | long |
c | str | char |
d | float | double |
D | complex | Py_Complex* |
O | (any) | PyObject* |
S | str | PyStringObject |
则第一步的代码修改为:
//1、包含Python的头文件
#include<Python.h>
#include<stdio.h>
int fac(int i){
if(i<2) return 1;
else return i*fac(i-1);
}
//2、为每个模板的每一个函数增加一个形如PyObject* Module_func()的包装函数
static PyObject* test_fac(PyObject* self, PyObject* args){
int num;
if(!PyArg_ParseTuple(args, "i", &num))
return NULL;
return (PyObject*)Py_BuildValue("i", fac(num));
}
//3、为每个模板增加一个形如PyMethodDef ModuleMethos[]的数组
static PyMethodDef testMethods[]={
{"fac", test_fac, METH_VARARGS},
{NULL, NULL},
};
//4、增加模块初始化函数void initModule()
void inittest() {
Py_InitModule("test", testMethods);
}
三、编译
分4步骤
1、创建setup.py
2、通过运行setup.py来编译和连接代码
3、从Python中导入模块
4、测试功能
setup.py
from distutils.core import setup, Extension
MOD='test'
setup(name=MOD, ext_modules=[
Extension(MOD, sources=['test.c'])])
编译
python setup.py build
python setup.py install
测试:
import test
test.fac(5)