Search code examples
pythoncbufferpython-cffi

Create a CData-typed buffer in Python with CFFI


I am trying to create a buffer with a special type in Python, to send it to a C function wrapped with CFFI.

In C, I have something like:

typedef unsigned char UINT8;
typedef UINT8* PUINT8;

Then, in Python, the above lines are in the ffi.cdef() and my buffer instantiation code looks like:

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 )

The C function receives a UINT8**.

And... that ends with a segmentation fault a little bit further, in the C function.

So I print buffers[ i ] after using ffi.cast:

<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>

What am I missing? Is the buffer being garbage collected as soon as it overwrites tmp_buffer?


Solution

  • How about:

    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