Ryan May wrote:
> Hi,
>> Can someone explain the reference counting wrt using ctypes and numpy.
> Specifically, I have code like:
>> from ctypes import *
> import numpy as N
>> class Data(Structure):
> _fields_=[('var',POINTER(c_float))]
>> d = Data()
> d.var = N.arange(100., dtype=N.float32).ctypes.data_as(POINTER(c_float))
> print d.var[5] #Should be 5.0
>> Instead it prints 0.0. (On my bigger code, it just segfaults.)
> Obviously, the array going in get's collected b/c its reference count
> goes to 0. Why does getting the data as a pointer not add a reference?
>The problem is that there is no way to keep a reference to some "memory"
in the ctypes "POINTER" object, that I know of.
So, when using POINTERS to memory like this you've got to make sure the
array does not disappear before you start using it (i.e you have to keep
references around yourself).
So, the solution is to:
1) Keep track of the memory yourself (by keeping a reference to the
array while you call the "heavy-lifting" code).
2) Let another part of the C-code, allocate and free memory and then you
just wrap it with NumPy array's for manipulation in Python (i.e. using
frombuffer or the ndarray constructor).
> Is there a "correct" way to do what I'm attempting?
>> Overall, I'm trying to create arrays using Numpy that are saved into
> structures and passed into ctypes-wrapped C code that does the heavy
> lifting. However, this heavy lifting is done in a different (ie.
> separate and higher) scope than the code that creates the arrays.
>>I'm not sure what "higher" in this context means.
Specific to your example, I would do the following:
from ctypes import *
import numpy as np
d = Data()
d.a = np.arange(100.,dtype=np.float32)
d.var = d.a.ctypes.data_as(POINTER(c_float))
d.var[5]
Now, the memory for a will not go away until you delete d (or d.a)
-Travis O.