I have a C library that is compiled to a shared object and want to build a ctypes interface around it to call the C functions from Python.
In general it works fine but there is this definition of a double array in the C library:
typedef double __attribute__ ((aligned (32))) double_array[512];
I found no way to access this type directly, so I defined in Python:
DoubleArray = ctypes.c_double * 512
While this works out in most cases, sometimes the C library segfaults and I guess this happens because DoubleArray
is not aligned to 32 bytes (maybe the library expects this because the data is passed to AVX).
How can I solve this problem?
The array is at most 31 bytes shy of alignment. To get an aligned array, over-allocate by 31 bytes and then, if the base address is misaligned, add an offset to make it aligned. Here's a generic function for this:
def aligned_array(alignment, dtype, n):
mask = alignment - 1
if alignment == 0 or alignment & mask != 0:
raise ValueError('alignment is not a power of 2')
size = n * ctypes.sizeof(dtype) + mask
buf = (ctypes.c_char * size)()
misalignment = ctypes.addressof(buf) & mask
if misalignment:
offset = alignment - misalignment
else:
offset = 0
return (dtype * n).from_buffer(buf, offset)
For example:
>>> arr = aligned_array(2**4, ctypes.c_double, 512)
>>> hex(ctypes.addressof(arr))
'0x1754410'
>>> arr = aligned_array(2**8, ctypes.c_double, 512)
>>> hex(ctypes.addressof(arr))
'0x1755500'
>>> arr = aligned_array(2**12, ctypes.c_double, 512)
>>> hex(ctypes.addressof(arr))
'0x1757000'
>>> arr = aligned_array(2**16, ctypes.c_double, 512)
>>> hex(ctypes.addressof(arr))
'0x1760000'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With