lua-users home
lua-l archive

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


Francesco Abbate wrote:
> just a small question. I've seen that if you define a metatype for a
> 'struct foo' and you have a cdata that is a 'struct foo *' then
> metatables does not apply to this latter object.

Nope. Metamethods _do_ apply to pointers to structs, too:
  http://lua-users.org/lists/lua-l/2011-04/msg00490.html

Sometimes the pre-defined pointer operations get in the way,
e.g. p - q is pointer arithmetic. Use p[0] - q[0] instead.

> I mean, normally you can index both struct instance and pointer in the
> same way and for me it was logical that both types are associated to
> the same metatable but I'm not completely sure.

It's easy to make s.foo and p.foo do the same, but s[10] is
normally undefined whereas p[10] already has a definition: pointer
indexing, returning a ref to a struct here. So you need to use
p[0][10]. Or better use refs instead of pointers to avoid that.

> The __gc metamethod may be should not be the same for pointers
> and struct of the same type.

The __gc metamethod only applies to structs that are allocated
with ffi.new(). It never applies to pointers or refs. It's most
useful to release resources _associated_ with a struct (e.g.
interior pointers to malloc()'ed memory).

Maybe you're confusing this with ffi.gc(), which is a lower-level
mechanism. It can be applied to aggregates _or_ pointers/refs.
It's most useful when the resource to be released comes as a
pointer from a C function (e.g. a FILE *).

>    local m = gsl_matrix {n1, n2, n2, block.data, block, 1}

Stylistic notice: there's no need to create a temporary table.
Initializers for structs take multiple arguments.

> My problem here is that by calling gsl_matrix_alloc I get a pointer
> and not a struct instance and so the metatable that I can associate to
> a 'gsl_matrix' does not apply.

But it does apply. And if you need to automatically free the
matrix, then attach a finalizer to the pointer with ffi.gc().
You need to pass the pointer around and keep it alive, of course.

In your case it's probably easiest to declare the C function with
a reference return value:

ffi.cdef[[
gsl_matrix &gsl_matrix_alloc(...);
]]

ffi.metatype("gsl_matrix", { ... })

function matrix.new(...)
  return ffi.gc(cgsl.gsl_matrix_alloc(...), cgsl.gsl_matrix_free)
end

--Mike