您的位置:首页 > 编程语言 > Python开发

菜鸟级别的Python扩展C的实现

2017-03-07 21:42 781 查看
关于Python扩展C有很多大牛写的博客很是齐全,我就从0基础那是假的,有一点点基础,开始整合一下Python调用C的动态链接库的实现。开发基于windows 环境,Python2.7,C编译用的VS2015。

关于Python扩展C有很多的方法,采用调用动态链接库是我觉得比较简单和有效的方法。这方面知识的介绍下面的文章介绍的十分详细哈:

http://baidutech.blog.51cto.com/4114344/743673/

http://www.isnowfy.com/introduction-to-python-c-extension/%20%20%E5%90%84%E7%A7%8DPython%E6%89%A9%E5%B1%95C/C++%E6%96%B9%E6%B3%95)

一开始明确自己的意图,根据自己的需求和使用的方法选择一种方式。本人尝试了API形式的C扩展,但是由于对Python底层的实现不是很了解,止步于结构体的参数传递,为了解决这个问题到了动态链接库的实现。

相对于API方法来讲,dll的实现相对简单的多了,我们只需要把Python中计算量大的方法用C实现,然后再VS中编译成dll文件,然后使用ctypes方法就行了。具体的关于动态链接库的实现见下面的链接:

http://m.blog.csdn.net/article/details?id=52550332

结构体类型和结构体数组类型的传递

实例代码C源码:

#define Tskstu struct Taskstu
struct Taskstu
{
int s;
int c[20];
int m[20];
int T;
};

____declspec(dllexport) float CalList(Tskstu * iTsets,int len)


注意,我们是用c写的代码,所以不用加 extern “C”语句,C++的话需要加改语句。CalList 函数的功能是计算结构体数组中∑si=0c[i]∗m[i]T之和的,所以返回的是个浮点型。这个功能并不重要,重要的是CalList的参数是一个结构体数组和一个整形,返回类型是个浮点型。这个函数充分能反应今天要解决的结构体和结构体数组的问题。

解决方法如下:

1.使用ctypes方法,在Python代码中生成一个如C中的结构体:

from ctypes import *
import time
class CrandStruct(Structure):
_fields_=[('si',c_int),
('ci',c_int *20),
('mi', c_int * 20),
('ti', c_int)
]


注意,c_int *20 的意思是该参数是一个长度为20的整形数组。该结构体要和c代码中的结构体对应起来

2. 生成一个大小为len的结构体数组:

StrctSet=(CrandStruct * len)()


并对该结构体数组赋值,具体操作就不赘述了。

3.引入对应的C源码的dll文件:

dllpath="D:\\dllgenerate\\Debug\\dllgenerate.dll"
libc=cdll.LoadLibrary(dllpath)


为了方便,可以把动态链接库文件拷贝到Python工程对应的目录下,方便操作

4.对返回类型进行确认

libc.CalList.restype=c_float


5.调用动态链接库中的功能函数

U=libc.CalList(byref(StrctSet),len)


酱酱,大功告成咯

看起来干货没多少,可是折腾了2天呢。记录一下,具体的各种扩展方法之间的区别和速度,有很多牛人做了总结,多看,就能避免走弯路了,话说折腾这么久就是因为走了弯路呢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息