在Python ctypes中控制内存对齐
我正在研究如何使用ctypes来调用C语言的函数,这些函数需要处理SSE(__m128)数据,而这些数据必须在16字节的边界上对齐。
我找不到简单的方法来控制ctypes分配的内存对齐,所以现在我让ctypes调用一个C函数,这个函数提供了一个正确对齐的内存缓冲区。
我遇到的问题是,我必须手动明确释放这块内存,以防止内存泄漏。
有没有办法控制ctypes分配的内存对齐?或者有没有办法注册一个清理函数来释放由ctypes调用的C函数分配的内存(除了标准的Python操作符__del__)?
我应该走哪条路比较好?
2 个回答
1
我想说,c_ulonglong
(64位)应该是64位对齐的,这算是一个开始。接着,文档建议你可以使用 _pack_
来控制结构体的对齐方式。这两者虽然不是你想要的完全解决方案,但结合起来可以让你分配8字节对齐的结构体,而且没有空隙。
假设有一个结构体里面有3个8字节对齐的元素 .v0
、.v1
和 .v2
。可以用 addressof()
来检查这个结构体是否是16字节对齐的。如果是,就用 .v0
和 .v1
来表示你的128位值;如果不是,就用 .v1
和 .v2
。
4
我花了一些时间研究,想出了一个函数,这个函数应该能让我用ctypes分配任意对齐的内存。基本上是依靠ctypes会保持对未对齐内存缓冲区的引用,同时在缓冲区中有一个从对齐位置开始的实例。
不过我还需要在实际环境中测试一下这个方法。
import ctypes
def ctypes_alloc_aligned(size, alignment):
bufSize = size+(alignment-1)
raw_memory = bytearray(bufSize)
ctypes_raw_type = (ctypes.c_char * bufSize)
ctypes_raw_memory = ctypes_raw_type.from_buffer(raw_memory)
raw_address = ctypes.addressof(ctypes_raw_memory)
offset = raw_address % alignment
offset_to_aligned = (alignment - offset) % alignment
ctypes_aligned_type = (ctypes.c_char * (bufSize-offset_to_aligned))
ctypes_aligned_memory = ctypes_aligned_type.from_buffer(raw_memory, offset_to_aligned)
return ctypes_aligned_memory