我想在Python中将内存缓冲区定义为数组,这些数组作为指针数组传递给C函数。 C函数在返回之前用缓冲区填充数据。 C API是用于访问我使用ctypes包装的ETTUS B210软件定义无线电的DLL。我简化了下面的代码,只是为了展示我想要做的事情的基本要素。
我在单个线程中工作但如果缓冲区在主线程中定义且API调用在一个单独的进程中,则无法实现相同的功能。乍一看multiprocessing.RawArray是我需要的,但我找不到一种方法来访问底层数据存储器作为一个指针,我可以在调用C函数时传输。
我需要使用多个进程,部分原因是因为硬件的C API(不是我写的)一次只处理一个硬件设备,但可以运行多个实例。
我以这种方式处理缓冲区的原因主要是速度 - 数组可能非常大> 2000000浮点数并且一遍又一遍地使用,所以我想分配一次并重用。将数据通过管道从一个过程传递到另一个过程是一个巨大的瓶颈 - 虽然它确实有点工作。
作为一个单独的线程我做这样的事情:
def stream(n_samples, buffer1, buffer2):
buffer_list = (c_void_p*2)()
buffer_list[0] = cast( pointer( buffer1 ), c_void_p )
buffer_list[1] = cast( pointer( buffer2 ), c_void_p )
windll.myapi.stream(c_int(n_samples), byref(buffer_list))
if __name__ == '__main__':
buf1 = ( c_float * ( 2*n_samples))()
buf2 = ( c_float * ( 2*n_samples))()
stream(n_samples, buf1, buf2)
如果stream()
现在已成为流程的一部分,我尝试了这一点,但它没有按照我的意愿行事:
buf1 = RawArray('f', 2*n_samples)
buf2 = RawArray('f', 2*n_samples)
p1 = process(target=stream, args=(n_samples, buf1, buf2,))
p1.start()
p1.join()
尽管API似乎在某处填充了内存(并且没有抛出异常,这是我在指针定义错误时通常会发生的情况),但是无法通过buf1, buf2
对象访问它。
作为附录:我使用了几个缓冲区,在单线程版本中我定义了一个大缓冲区,然后计算传递给API的偏移指针。在多处理版本中执行此操作会很有用,但不是必需的。