介绍
前段时间在做信号分析与处理项目的时候,需要通过快速傅立叶变换将时域数据转换到频域,以便进一步的后续处理。由于实时运算速度的要求,我需要考虑程序算法的性能。因此,用C语言完成了信号处理算法,然后将算法的实现功能封装成一个动态链接库文件。最后我用Python调用了DLL文件中的函数,通过GUI界面程序图形化的显示了运算结果。这就涉及到如何将C语言中复杂的数组类型与Python中的数据类型进行交互。

在Python语言中,可以使用ctypes模块调用其他用C++语言编写的DLL文件中的函数。在前面的文章中,已经提到了传递数字/指针/字符串参数、传递结构参数和传递通用数组类型的例子。可以回顾一下,这样可以更好的理解你这次要讲的内容。
此示例的运行环境配置如下:
①操作系统:64位win7
② Python版本:python2.7.14
③功能约定的通话模式:C通话模式。
具体实现过程如下。
功能描述
DLL文件中设计了一个函数ComplexArrayFunc。它的作用是将输入长度为n的复数组X中每个复元素的实部和虚部进行交换,得到相同长度的复数组Y。该函数的声明如下图所示:
函数ComplexArrayFunc的具体C语言实现代码如下:
下面是Python中转换为numpy数组的调用方法。

Python中的调用方法
如前几篇文章所述,可以考虑直接使用ctypes模块将上述函数中的复杂数组X声明为复杂类型的指针,即以“point”的形式。但是在ctypes模块中声明指针类型时,模块中没有c_complex类型的指针,所以这个方法不容易实现。
一般来说,C语言和Python语言用DLL文件编程时,DLL函数中的数组类型可以转换成numpy库中的数组类型。这样做的好处是可以借助numpy强大的分析处理功能直接处理数据。
在numpy库中,直接支持复杂数组类型的声明。
根据这个想法,Python中的函数声明和调用如下:
上述方法中,在声明函数的参数类型时,对于参数x和y类型复杂的指针变量,使用np.ctypeslib.ndpointer直接将numpy中的数组声明为C语言中的复杂数组类型。最后,numpy中的数组类型A和B被传递给函数。
需要注意的是,复数类型的指针X和Y的类型要声明为np.complex128,因为在C语言中,指针X和Y的实部和虚部都是double类型的数据,所以numpy中对应的复数类型是8*2=16Bytes=128bits。
在Python中使用这种调用方法的好处是,只需要在文件中声明一次函数原型。虽然声明起来比较麻烦,但是在Python中可以在很多地方多次调用该函数,不需要额外的转换工作就可以直接使用numpy中的数组类型。
完整的测试代码
完整的测试代码如下图所示:

操作结果如下图所示:
从运行结果可以看出,包含三个复数元素的数组A的实部和虚部已经互换,复数数组B已经正确输出。这种调用方法可以实现C语言复数组和numpy复数组之间正确的数据传递。
摘要
从这个例子可以看出,在Python中,通过ctypes模块调用用C++语言编写的其他DLL文件中的函数,不仅可以提高软件的运行效率,还可以充分利用目前市面上各种第三方DLL库函数,从而扩展Python软件的功能和应用领域,减少重复编写代码和构建轮子的工作量,充分体现了Python作为一种胶水语言的独特优势。
本文由编码那些事原创,请关注+转发+收藏+点赞,带你一起学习!


