2016-03-22 6 views
3

共有オブジェクトにコンパイルされたCライブラリがあり、PythonからC関数を呼び出すためのctypesインタフェースを構築したいと考えています。Python ctypesはデータ構造を整列します

一般的には、それが正常に動作しますが、Cライブラリ内のdouble配列のこの定義があります:

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

私はこのタイプを直接アクセスする方法を発見したので、私はPythonで定義された:

DoubleArray = ctypes.c_double * 512 

ほとんどの場合、Cライブラリのセグメンテーションが正しく行われないことがありますが、DoubleArrayが32バイトにアライメントされていないため、この問題が発生していると思います(データはAVXに渡されるため、

どうすればこの問題を解決できますか?

答えて

2

配列は最大31バイトの位置合わせが可能です。配置された配列を取得するには、31バイトをオーバー・アロケートしてから、ベース・アドレスの位置がずれている場合は、オフセットを加算して整列させます。ここでは、このための一般的な機能があります:たとえば

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' 
関連する問題