关于Python扩展C有很多大牛写的博客很是齐全,我就从0基础那是假的,有一点点基础,开始整合一下Python调用C的动态链接库的实现。开发基于windows 环境,Python2.7,C编译用的VS2015。
关于Python扩展C有很多的方法,采用调用动态链接库是我觉得比较简单和有效的方法。这方面知识的介绍下面的文章介绍的十分详细哈:
http://baidutech.blog.51cto.com/4114344/743673/
一开始明确自己的意图,根据自己的需求和使用的方法选择一种方式。本人尝试了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天呢。记录一下,具体的各种扩展方法之间的区别和速度,有很多牛人做了总结,多看,就能避免走弯路了,话说折腾这么久就是因为走了弯路呢。