Skip to content
This repository has been archived by the owner on Nov 4, 2023. It is now read-only.

Commit

Permalink
add __new metamethod support
Browse files Browse the repository at this point in the history
  • Loading branch information
justincormack committed Oct 6, 2013
1 parent ecf7848 commit 6ef2e4a
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 4 deletions.
33 changes: 29 additions & 4 deletions ffi.c
Expand Up @@ -1138,6 +1138,33 @@ static int ffi_new(lua_State* L)
static int ffi_cast(lua_State* L)
{ return do_new(L, 1); }

static int ctype_new(lua_State* L)
{ return do_new(L, 0); }

static int ctype_call(lua_State* L)
{
struct ctype ct;
int top = lua_gettop(L);

check_ctype(L, 1, &ct);

if (push_user_mt(L, -1, &ct)) {
lua_pushstring(L, "__new");
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
lua_insert(L, 1); // function at bottom of stack under args
lua_pop(L, 2);
lua_call(L, top, 1);
return 1;
}
lua_pop(L, 2);
}
lua_pop(L, 1);

assert(lua_gettop(L) == top);
return do_new(L, 0);
}

static int ffi_sizeof(lua_State* L)
{
struct ctype ct;
Expand Down Expand Up @@ -1392,7 +1419,6 @@ int push_user_mt(lua_State* L, int ct_usr, const struct ctype* ct)
lua_pop(L, 1);
return 0;
}

return 1;
}

Expand Down Expand Up @@ -1784,15 +1810,13 @@ static int call_user_op(lua_State* L, const char* opfield, int idx, int ct_usr,
if (push_user_mt(L, ct_usr, ct)) {
lua_pushstring(L, opfield);
lua_rawget(L, -2);

if (!lua_isnil(L, -1)) {
int top = lua_gettop(L);
lua_pushvalue(L, idx);
lua_call(L, 1, LUA_MULTRET);
return lua_gettop(L) - top + 1;
}
}

return -1;
}

Expand Down Expand Up @@ -2831,7 +2855,8 @@ static const luaL_Reg callback_mt[] = {
};

static const luaL_Reg ctype_mt[] = {
{"__call", &ffi_new},
{"__call", &ctype_call},
{"__new", &ctype_new},
{"__tostring", &ctype_tostring},
{NULL, NULL}
};
Expand Down
26 changes: 26 additions & 0 deletions test.lua
Expand Up @@ -818,5 +818,31 @@ assert(d[2] == 1)
ffi.fill(d, 3)
assert(d[2] == 0)
-- tests for __new
ffi.cdef[[
struct newtest {
int a;
int b;
int c;
};
]]
local tp = ffi.metatype("struct newtest", {__new =
function(tp, x, y, z)
tp = ffi.new(tp)
tp.a, tp.b, tp.c = x, y, z
return tp
end})
local v = tp(1, 2, 3)
assert(v.a == 1 and v.b == 2 and v.c == 3)
local tp = ffi.metatype("struct newtest", {__new =
function(tp, x, y, z)
tp = ffi.new(tp, {a = x, b = y, c = z})
return tp
end})
local v = tp(1, 2, 3)
assert(v.a == 1 and v.b == 2 and v.c == 3)
print('Test PASSED')

0 comments on commit 6ef2e4a

Please sign in to comment.