Re: FFI methods for userdata objects

  • From: Mike Pall <mike-1209@xxxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Thu, 6 Sep 2012 11:45:53 +0200

Simon Cooke wrote:
> It seems that __len does work, but needs the signature
> len(void * a, void *) with an extra dummy argument [1].

That's a side-effect of the metamethod handling of Lua 5.1, where
the __len metamethod always gets two arguments. I can't do much
about that without breaking compatibility.

> However, __newindex gives the following error:
> 
>     'void ()' cannot be indexed with 'number'

Ah, I forgot: __index and __newindex needs to make a decision
whether to call or to index its value. It's hard to distinguish
between generically callable vs. indexable objects. So the rule in
Lua 5.1 is that plain functions are callable, but everything else
(including cdata) is indexed. That's why you get this error.

[Also, even if one would make an exception for cdata functions,
these would need an extra __call dispatch, which runs into the
same problem as for a __call metamethod itself.]

> My specific use case is a class for large arrays (basically a C++
> std::vector<T>) using __call to read elements and __newindex to write.

Ok, if you need this is for interoperability. But you realize it
would be much faster to use a plain FFI data structure? This
doesn't need any C calls to index it.

> [TRACE --- test2.lua:13 -- leaving loop in root trace at test2.lua:26]

The error message is a bit misleading: it's not a loop, but it's
leaving the function that started the root trace. A function
ending in a tailcall always leaves the function, so it cannot be
compiled in isolation. So the outer loop is unrolled, but there
are limits to that and you hit the limit. Taken together neither
trace is ever compiled, so the code path is eventually blacklisted.

The simple workaround would be to use parentheses to prevent the
tailcall:

mt.__call = function(self,k) return (clib.get_double(self,k)) end -- line 13

--Mike

Other related posts: