StevenMurray
StevenMurray

Reputation: 752

Passing multiple numpy arrays to C using CFFI

I have the following (in real life, the C code is much more complex, and I don't want to change it. It uses globals everywhere).:

from cffi import FFI

ffibuilder = FFI()

ffibuilder.set_source(
    "mymodule",
    r"""
    #include <stdio.h>

    float *x, *y, *z;
    int n;

    void some_func(){
        int i;
        for(i==0; i<n; i++) printf("%f %f %f\n", x[i], y[i], z[i]);
    }
    """
)

ffibuilder.cdef(
    """
    float *x, *y, *z;
    int n;
    void some_func();
    """
)

if __name__=="__main__":
    ffibuilder.compile()

    from mymodule import ffi, lib
    import numpy as np

    n = 4
    lib.n = n

    for i, k in enumerate(['x','y', 'z']):
        v = i*np.arange(n, dtype=np.float32)
        v.__repr__() # Need to do this for some reason!!
        setattr(lib, k, ffi.cast('float*', ffi.from_buffer(v)))

    lib.some_func()

The expected printed output (from some_func) is:

0.000000 0.000000 0.000000
0.000000 1.000000 2.000000
0.000000 2.000000 4.000000
0.000000 3.000000 6.000000

And that is indeed what I get. However, if I take out the line where I call v.__repr__(), I get the following:

0.000000 0.000000 0.000000
1.000000 1.000000 2.000000
2.000000 2.000000 4.000000
3.000000 3.000000 6.000000

i.e. it seems like the memory of x is either being overwritten by y, or is pointing to y. If I have only x and y (no z), then things work as expected.

Using double instead of float exhibits the same behaviour.

Any ideas on what I'm doing wrong?? Thanks!

Upvotes: 3

Views: 441

Answers (1)

HYRY
HYRY

Reputation: 97321

Keep the array alive, otherwise they will be garbage collected:

arrs = []
for i, k in enumerate(['x','y', 'z']):
    v = i*np.arange(n, dtype=np.float32)
    arrs.append(v)
    ...

Upvotes: 2

Related Questions