Reputation: 752
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
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