2016-03-22 31 views
3

Paylaşılan bir nesneye derlenmiş bir C kütüphanem var ve Python'dan C işlevlerini çağırmak için etrafında bir klişe arabirimi oluşturmak istiyorum. Ben doğrudan bu tür erişmek için hiçbir şekilde bulunduPython ctypes veri yapısını hizala

typedef double __attribute__ ((aligned (32))) double_array[512]; 

, bu yüzden Python tanımlanan: sorunsuz çalışıyor ama C kütüphanesinde bir çift dizinin bu tanım yoktur Genelde

DoubleArray = ctypes.c_double * 512 

Bu, çoğu durumda, bazen C kütüphanesi segfaults ve out sanırım, bu DoubleArray 32 bayt ile hizalanmış değildir çünkü tahmin ediyorum (belki de veri AVX'e geçirildiği için kütüphane bunu bekliyor).

Bu sorunu nasıl çözebilirim?

cevap

2

Dizi en fazla 31 baytlık bir hizalama düzeyindedir. Hizalanmış bir dizi almak için, 31 bayttan fazla ayırın ve sonra temel adres yanlış hizalanmışsa, hizalamak için bir ofset ekleyin. Örneğin

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) 

:

>>> 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' 
İşte bunun için genel bir işlevi var