近段时间工作中,需要对一个算法的有效性做批量验证,这种活我一般都是用python + pySide搞定。验证通过之后,再转换为C代码。之前一直是这么做的,因为python调整算法很快。但这次的算法比较复杂,用python实现起来固然方便(list操作太方便了),却还要经过一道转换,需要做单元测试。为了充分发挥懒人精神,决定算法部分直接用C代码实现,python负责界面和数据加载及预处理(处理为产品上的数据格式)。花了点时间研究了一下ctypes,以下就是笔记,我重点应用的是数组/指针类型的参数。
其中比较tricky的一点就是用于C类型的数组入参初始化,先利用python的array模块将list转换为array,然后用array初始化C类型的数组。
#include <stdio.h>
__declspec( dllexport ) int func_test(unsigned short anInputSignal1[], int nLen1, unsigned short anInputSignal2[], int nLen2, unsigned short *pnOutput, int *pLen);
int func_test(unsigned short anInputSignal1[], int nLen1, unsigned short anInputSignal2[], int nLen2, unsigned short *pnOutput, int *pLen)
{
int i = 0;
for (i = 0; i < nLen1; i++)
{
printf("%d, ", anInputSignal1[i]);
}
printf("\n");
for (i = 0; i < nLen2; i++)
{
printf("%d, ", anInputSignal2[i]);
}
printf("\n");
for (i = 0; i < *pLen; i++)
pnOutput[i] = i;
*pLen = 1;
return 0;
}
编译成为 dll,放到python工程文件夹下,test.py内容如下:
import ctypes
import array
inputSignal1 = array.array('H')
inputSignal1.fromlist(range(1, 10))
inputSignal2 = array.array('H')
inputSignal2.fromlist(range(11, 20))
cInputArrayType = (ctypes.c_ushort * len(inputSignal1))
cInputSignal1 = cInputArrayType(*inputSignal1)
cInputSignal2 = cInputArrayType(*inputSignal2)
cOutputArray = (ctypes.c_ushort * 10)()
cOutLen = ctypes.c_int(10)
mydll = ctypes.CDLL('ctypes.test.dll')
mydll.func_test(cInputSignal1,
ctypes.c_int(len(inputSignal1)),
cInputSignal2,
ctypes.c_int(len(inputSignal2)),
cOutputArray,
ctypes.byref(cOutLen))
print cOutLen.value
for data in cOutputArray:
print data
其中比较tricky的一点就是用于C类型的数组入参初始化,先利用python的array模块将list转换为array,然后用array初始化C类型的数组。
输出如下:
1, 2, 3, 4, 5, 6, 7, 8, 9,
11, 12, 13, 14, 15, 16, 17, 18, 19,
1
0
1
2
3
4
5
6
7
8
9
剩下的数据类型可以参考文档,写的挺好的,就是初始化部分开始让我有些纠结,呵呵。