python用什么来写模块-Python 3.1 用C写模块 扩展(序)

注意。此方式只在win下用vc2008成功。其他编译器/环境未试验:

1。 在vc中建立一个dll的project。 假定我们的module的名字是mytest.那么我们的dll名字就是mytest.dll。 这个是必须的。

2。 用c写我们想要实现的部分。步骤如下

#include //这个是必须的。python的类型都在这里定义。

static PyObject* my_strlen(PyObject *self, PyObject *args)

{char *string;intlen;if (!PyArg_ParseTuple(args, "s", &string))returnNULL;

len= strlen(string);return Py_BuildValue("i", len);

}static PyObject* my_strcat(PyObject *self, PyObject *args)

{char*string1;char*string2;char*newstring;if (!PyArg_ParseTuple(args, "s|s", &string1, &string2))returnNULL;

newstring=strcat(string1, string2);return Py_BuildValue("s", newstring);

}

第一个参数是self,这个是python用的, 每个函数都要有。我们暂时不管。args是一个参数列表。她把所有的参数都整合成一个string。所以

我们需要从这个string里来解析我们的参数。

PyArg_ParseTuple来完成这个任务。第一个参数是args, 就是我们要转换的参数。第二个是格式符号。"s”代表是个string。 从args里

提取一个参数就写"s", 两个的话就写"s|s", 如果是一个string,一个int,就写"s|i", 和printf差不多。第三个参数就是提取出来的

参数放置的真正位置。必须传递这个参数的地址。对于my_strcat, 他将提取两个参数。分别是string1和string2。

然后调用真正的我们的实现。分别是strlen和strcat。

调用完之后我们需要返回结果。这个结果是c的type或者是我们自己定义的类型。必须把他转换成PyObject, 让python认识。这个用Py_BuildValue

来完成。他是PyArg_ParseTuple的逆过程。他的第一个参数和PyArg_ParseTuple的第二个参数一样, 是个格式化符号。第三个参数

是我们需要转换的参数。Py_BuildValue会把所有的返回只组装成一个tutple给python。

实际上,我们只是把我们想要实现的部分调用python提供的api来封装了一下。但是python并不知道怎么用这些函数。

我们还需要做一些工作。

static PyMethodDef mytestMethods[] ={

{"mystrlen", my_strlen, METH_VARARGS, "We test strlen of C"},

{"mystrcat", my_strcat, METH_VARARGS, "We test strcat of C"},

{NULL, NULL,0, NULL}

};

这个是一个c的结构。他来完成一个映射。 我们需要把我们扩展的函数都映射到这个表里。表的第一个字段是python真正认识的。是python

里的方法名字。 第二个字段是python里的这个方法名字的具体实现的函数名。 在python里调用mystrlen, 真正执行的是用c写的

my_strlen函数。第三个字段是METH_VARARGS, 他告诉python,mystrlen是调用c函数来实现的。第四个字段是这个函数的说明。如果你在

python里来help这个函数,将显示这个说明。相当于在python里的函数的文档说明。

我们建立了这个映射表。这个表是在python导入我们的这个module的时候来用的。

/*下面就和2.x版本的约定不同了*/

static PyMethodDef mytestMethods[] ={

{"mystrlen", my_strlen, METH_VARARGS, "We test strlen of C"},

{"mystrcat", my_strcat, METH_VARARGS, "We test strcat of C"},

{NULL, NULL,0, NULL}

};char name[] = "mytest";staticPyModuleDef mytestModule;//对于其他平台。函数的修饰符可能不同

_declspec(dllexport)voidPyInit_mytest()

{

mytestModule.m_methods= mytestMethods;//模块的方法表

mytestModule.m_name = name;//模块说明

PyModule_Create2(&mytestModule, PYTHON_API_VERSION);

}

注意,这个函数的名字不能改动。 必须是PyInit_+模块名字。 我们的模块名字是mytest。所以这个函数是PyInit_mytest()。 这个函数应该被 导出。所以使用 _declspec(dllexport)。 这样python在导入mytest 的模块时候,才会找到这个函数,并调用。

a. 当我们import mytest的时候。 python装载这个module的dll。 在这里是mytest.dll

b. 然后在这个dll里调用, PyInit_mytest函数来建立一个映射表。 如果这个initmytest函数不实现或者没有导出。就不能成功把这个module

导入到python里。

c. python 从映射表 知道这个模块实现了几个方法。并且名字分别是什么。当调用他们的时候,找到相应的c的函数。

写完这些代码以后,我们可以在vc里编译这个dll, 注意,必须编译成release版本。编译的dll名字是mytest.dll。如果不是的话,在vc里改动link的设置。

把mytest.dll改名为mytest.pyd,然后拷到python3的DLLs目录下

#test.py 测试代码

import mytest

print(mytest.mystrlen("123") )

print(mytest.mystrcat("123", "456"))

应该输出:

3

123456

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值