2016-05-13 21 views
2

Ich versuche, einen Puffer mit einem speziellen Typ in Python zu erstellen, um es an eine C-Funktion zu senden, die mit CFFI umwickelt wird.Erstellen Sie einen CData-typed Puffer in Python mit CFFI

In C, ich habe so etwas wie:

typedef unsigned char UINT8; 
typedef UINT8* PUINT8; 

Dann in Python sind die obigen Zeilen in der ffi.cdef() und mein Puffer Instanziierung Code wie folgt aussieht:

nb_buffer = 8 
buffer_size = 42 

buffers = ffi.new("PUINT8[]", nb_buffer) 

for i in range(nb_buffer): 
    tmp_buffer = ffi.buffer(ffi.new("UINT8[]", 1), buffer_size) 
    buffers[ i ] = ffi.cast("PUINT8", ffi.from_buffer(tmp_buffer)) 

c.function(buffers) 

Die C-Funktion erhält ein UINT8 **.

Und ... endet mit einem Segmentierungsfehler ein wenig weiter, in der C-Funktion.

Also ich print buffers[ i ] nach ffi.cast mit:

<cdata 'unsigned char *' 0x2cbaca0> 
<cdata 'unsigned char *' 0x2cbacd8> 
<cdata 'unsigned char *' 0x2cbaca0> 
<cdata 'unsigned char *' 0x2cbacd8> 
<cdata 'unsigned char *' 0x2cbaca0> 
<cdata 'unsigned char *' 0x2cbacd8> 
<cdata 'unsigned char *' 0x2cbaca0> 
<cdata 'unsigned char *' 0x2cbacd8> 

Was bin ich? Wird der Puffer als Müll gesammelt, sobald er überschreibt?

+0

nicht in Details suchen, aber '' ffi.buffer (ffi.new ("UINT8 []", 1). ..) '' ist grundsätzlich falsch. Es bedeutet "ein Array (von einem UINT8) zuweisen; dann nehmen Sie einen Puffer zu ihm; dann vergessen Sie sofort das neue Array, so dass es sofort freigegeben wird". –

+0

Sie reservieren auch Arrays von einem UINT8 und betrachten sie dann als 42-Byte-Puffer. Die letzten 41 Bytes sind sowieso nicht vergeben. –

+0

Ich dachte, die Wichtigkeit des ersten Parameters von 'ffi.buffer()' sei der Typ des CData, nicht seine Länge (wie es der zweite Parameter ist) und dass es irgendwie einen gegebenen CData-typisierten Puffer des erstellen würde gegebene Größe. Aber ich verstehe jetzt, dass dieser zweite Parameter eine Speichergröße schneidet, die größer als benötigt ist. Danke Armin! Ich werde deine Antwort so schnell wie möglich versuchen. – DRz

Antwort

1

Wie wäre:

buffers = ffi.new("PUINT8[]", nb_buffer) 
keepalive = [] 

for i in range(nb_buffer): 
    p = ffi.new("UINT8[]", buffer_size) 
    keepalive.append(p) 
    buffers[i] = p 

c.function(buffers) 

# keepalive stays alive at least until here 
0

Mit Liste Verständnis:

keepalive = [ ffi.new("UINT8[]", buffer_size) for i in range(nb_buffer) ] 
buffers = ffi.new("PUINT8[]", keepalive) 

c.functions(buffers) 

# keepalive stays alive at least until here