15.3 编写扩展函数操作数组

    为了能让接受和处理数组具有可移植性,你需要使用到 Buffer Protocol .下面是一个手写的C扩展函数例子,用来接受数组数据并调用本章开篇部分的 函数:

    下面我们演示下这个扩展函数是如何工作的:

    将一个数组对象传给C函数可能是一个扩展函数做的最常见的事。很多Python应用程序,从图像处理到科学计算,都是基于高性能的数组处理。通过编写能接受并操作数组的代码,你可以编写很好的兼容这些应用程序的自定义代码,而不是只能兼容你自己的代码。

    对于数组、字节字符串和其他类似对象而言,一个 结构体包含了所有底层内存的信息。它包含一个指向内存地址、大小、元素大小、格式和其他细节的指针。下面是这个结构体的定义:

    本节中,我们只关注接受一个双精度浮点数数组作为参数。要检查元素是否是一个双精度浮点数,只需验证 format 属性是不是字符串”d”.这个也是 struct 模块用来编码二进制数据的。通常来讲,format 可以是任何兼容 模块的格式化字符串,并且如果数组包含了C结构的话它可以包含多个值。一旦我们已经确定了底层的缓存区信息,那只需要简单的将它传给C函数,然后会被当做是一个普通的C数组了。实际上,我们不必担心是怎样的数组类型或者它是被什么库创建出来的。这也是为什么这个函数能兼容 array 模块也能兼容 numpy 模块中的数组了。

    在返回最终结果之前,底层的缓冲区视图必须使用 PyBuffer_Release() 释放掉。之所以要这一步是为了能正确的管理对象的引用计数。

    如果你需要编写涉及到数组处理的多个扩展,那么通过Cython来实现会更容易下。参考15.11节。

    原文: