lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Francesco Abbate wrote:
> I'm using ffi.cdef for the following struct/functions:
> 
> ---------
> typedef struct
> {
>   size_t size;
>   size_t *data;
> } gsl_permutation;
> 
> gsl_permutation *gsl_permutation_calloc (const size_t n);
> void gsl_permutation_init (gsl_permutation * p);
> void gsl_permutation_free (gsl_permutation * p);
> --------------

Why do you need to use C calls for that? Assuming the data part
doesn't grow after allocation you could use a variable-length
struct instead:

ffi.cdef[[
typedef struct {
  size_t size;
  size_t data[?];
} gsl_permutation;
]]

local p = ffi.new("gsl_permutation", 5)
p.size = 5

This nicely avoids the GC issues, too.

BTW: The use of size_t for anything but actual memory sizes is not
     a good idea. I guess int32_t would be a much better fit here.

> p = ffi.C.gsl_permutation_calloc(5)
> ffi.gc(p, ffi.C.gsl_permutation_free)

It doesn't make a difference here, but always use it like this:

local p = ffi.gc(ffi.C.gsl_permutation_calloc(5), ffi.C.gsl_permutation_free)

> where p is actually a local variable. The problem is that in this case
> I can get memory corruption and it seems that it happens when p is
> garbage-collected. I don't understand why... I'm doing something wrong?

Either you're dropping the last reference to p too early or
something is wrong with the deallocation function.

> The following variant seems to work:
> 
> p = ffi.new('gsl_permutation[1]')
> local data = ffi.new(string.format('size_t[%i]', nr))

Uh, why this? Neither do you need to create a 1-element array of a
struct, nor is there any necessity to use string.format for a
variable-length array:

local p = ffi.new("gsl_permutation")
local data = ffi.new("size_t[?]", nr)

> but in this case there is a problem: luajit is not aware that p
> depends on data and so it can collect data when p is still around. I
> was able to find a solution by storing the cdata objects in a table
> but I'm wondering what is the best method to do that correctly.

Keep it in one combined (variable-length) struct. Or use a plain
Lua table for more complex linked data structures. It's unlikely
to make much of a difference, except for big arrays.

--Mike