mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 15:14:08 +00:00
FFI: Handle __pairs/__ipairs metamethods for cdata objects.
This commit is contained in:
parent
90ec1f90d0
commit
0648fd47cb
@ -525,7 +525,16 @@ Returns a string representation of the value of 64 bit integers
|
||||
complex numbers (<tt><b>"</b>re±im<b>i"</b></tt>). Otherwise
|
||||
returns a string representation of the C type of a ctype object
|
||||
(<tt><b>"ctype<</b>type<b>>"</b></tt>) or a cdata object
|
||||
(<tt><b>"cdata<</b>type<b>>: </b>address"</tt>).
|
||||
(<tt><b>"cdata<</b>type<b>>: </b>address"</tt>), unless you
|
||||
override it with a <tt>__tostring</tt> metamethod (see
|
||||
<a href="#ffi_metatype"><tt>ffi.metatype()</tt></a>).
|
||||
</p>
|
||||
|
||||
<h3 id="pairs"><tt>iter, obj, start = pairs(cdata)<br>
|
||||
iter, obj, start = ipairs(cdata)<br></tt></h3>
|
||||
<p>
|
||||
Calls the <tt>__pairs</tt> or <tt>__ipairs</tt> metamethod of the
|
||||
corresponding ctype.
|
||||
</p>
|
||||
|
||||
<h2 id="literals">Extensions to the Lua Parser</h2>
|
||||
|
@ -278,12 +278,16 @@ LJLIB_ASM(next)
|
||||
return FFH_UNREACHABLE;
|
||||
}
|
||||
|
||||
#ifdef LUAJIT_ENABLE_LUA52COMPAT
|
||||
#if defined(LUAJIT_ENABLE_LUA52COMPAT) || LJ_HASFFI
|
||||
static int ffh_pairs(lua_State *L, MMS mm)
|
||||
{
|
||||
TValue *o = lj_lib_checkany(L, 1);
|
||||
cTValue *mo = lj_meta_lookup(L, o, mm);
|
||||
if (!tvisnil(mo)) {
|
||||
if (
|
||||
#if !defined(LUAJIT_ENABLE_LUA52COMPAT)
|
||||
tviscdata(o) &&
|
||||
#endif
|
||||
!tvisnil(mo)) {
|
||||
L->top = o+1; /* Only keep one argument. */
|
||||
copyTV(L, L->base-1, mo); /* Replace callable. */
|
||||
return FFH_TAILCALL;
|
||||
|
@ -323,6 +323,30 @@ checkgc:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ffi_pairs(lua_State *L, MMS mm)
|
||||
{
|
||||
CTState *cts = ctype_cts(L);
|
||||
CTypeID id = ffi_checkcdata(L, 1)->ctypeid;
|
||||
CType *ct = ctype_raw(cts, id);
|
||||
cTValue *tv;
|
||||
if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
|
||||
tv = lj_ctype_meta(cts, id, mm);
|
||||
if (!tv)
|
||||
lj_err_callerv(L, LJ_ERR_FFI_BADMM, strdata(lj_ctype_repr(L, id, NULL)),
|
||||
strdata(mmname_str(G(L), mm)));
|
||||
return lj_meta_tailcall(L, tv);
|
||||
}
|
||||
|
||||
LJLIB_CF(ffi_meta___pairs)
|
||||
{
|
||||
return ffi_pairs(L, MM_pairs);
|
||||
}
|
||||
|
||||
LJLIB_CF(ffi_meta___ipairs)
|
||||
{
|
||||
return ffi_pairs(L, MM_ipairs);
|
||||
}
|
||||
|
||||
LJLIB_PUSH("ffi") LJLIB_SET(__metatable)
|
||||
|
||||
#include "lj_libdef.h"
|
||||
|
@ -162,6 +162,7 @@ ERRDEF(FFI_NUMARG, "wrong number of arguments for function call")
|
||||
ERRDEF(FFI_BADMEMBER, LUA_QS " has no member named " LUA_QS)
|
||||
ERRDEF(FFI_BADIDX, LUA_QS " cannot be indexed")
|
||||
ERRDEF(FFI_BADIDXW, LUA_QS " cannot be indexed with " LUA_QS)
|
||||
ERRDEF(FFI_BADMM, LUA_QS " has no " LUA_QS " metamethod")
|
||||
ERRDEF(FFI_WRCONST, "attempt to write to constant location")
|
||||
ERRDEF(FFI_NODECL, "missing declaration for symbol " LUA_QS)
|
||||
ERRDEF(FFI_BADCBACK, "bad callback")
|
||||
|
10
src/lj_obj.h
10
src/lj_obj.h
@ -447,10 +447,12 @@ enum {
|
||||
#define MMDEF_FFI(_)
|
||||
#endif
|
||||
|
||||
#ifdef LUAJIT_ENABLE_LUA52COMPAT
|
||||
#define MMDEF_52(_) _(pairs) _(ipairs)
|
||||
#if defined(LUAJIT_ENABLE_LUA52COMPAT) || LJ_HASFFI
|
||||
#define MMDEF_PAIRS(_) _(pairs) _(ipairs)
|
||||
#else
|
||||
#define MMDEF_52(_)
|
||||
#define MMDEF_PAIRS(_)
|
||||
#define MM_pairs 255
|
||||
#define MM_ipairs 255
|
||||
#endif
|
||||
|
||||
#define MMDEF(_) \
|
||||
@ -460,7 +462,7 @@ enum {
|
||||
/* The following must be in ORDER ARITH. */ \
|
||||
_(add) _(sub) _(mul) _(div) _(mod) _(pow) _(unm) \
|
||||
/* The following are used in the standard libraries. */ \
|
||||
_(metatable) _(tostring) MMDEF_FFI(_) MMDEF_52(_)
|
||||
_(metatable) _(tostring) MMDEF_FFI(_) MMDEF_PAIRS(_)
|
||||
|
||||
typedef enum {
|
||||
#define MMENUM(name) MM_##name,
|
||||
|
Loading…
Reference in New Issue
Block a user