2012-06-19 58 views
9

我包裹和Lua C函数,使用的Lua 5.2的Lua-C API:如何在Lua-C API 5.2中创建一个类对象?

#include <lua.h> 
#include <lauxlib.h> 
#include <stdlib.h> 
#include <stdio.h> 

int foo_gc(); 
int foo_index(); 
int foo_newindex(); 
int foo_dosomething(); 
int foo_new(); 

struct foo { 
    int x; 
}; 

static const luaL_Reg _meta[] = { 
    {"__gc", foo_gc}, 
    {"__index", foo_index}, 
    {"__newindex", foo_newindex}, 
    { NULL, NULL } 
}; 
static const luaL_Reg _methods[] = { 
    {"new", foo_new}, 
    {"dosomething", foo_dosomething}, 
    { NULL, NULL } 
}; 

int foo_gc(lua_State* L) { 
    printf("## __gc\n"); 
    return 0; 
} 
int foo_newindex(lua_State* L) { 
    printf("## __newindex\n"); 
    return 0; 
} 
int foo_index(lua_State* L) { 
    printf("## __index\n"); 
    return 0; 
} 
int foo_dosomething(lua_State* L) { 
    printf("## dosomething\n"); 
    return 0; 
} 
int foo_new(lua_State* L) { 
    printf("## new\n"); 

    lua_newuserdata(L,sizeof(Foo)); 
    luaL_getmetatable(L, "Foo"); 
    lua_setmetatable(L, -2); 

    return 1; 
} 

void register_foo_class(lua_State* L) { 
    luaL_newlib(L, _methods); 
    luaL_newmetatable(L, "Foo"); 
    luaL_setfuncs(L, _meta, 0); 
    lua_setmetatable(L, -2); 
    lua_setglobal(L, "Foo"); 
} 

当我运行这个的Lua:

local foo = Foo.new() 
foo:dosomething() 

...我看到这个输出(有错误):

## new 
## __index 
Failed to run script: script.lua:2: attempt to call method 'dosomething' (a nil value) 

我在做什么错?谢谢

+0

尝试'对k,v对(getmetatable(foo))做print(k,v)end'。 – lhf

+2

在Lua 5.2中,您可以使用'luaL_setmetatable(L,“Foo”)'而不是'luaL_getmetatable(L,“Foo”); lua_setmetatable(L,-2);' – lhf

+1

OT:你不应该在C. – u0b34a0f6ae

回答

8

好的,得到它的工作。我不得不添加__index__metatableFoo的新的元表,如下图所示:

void register_foo_class(lua_State* L) { 
    int lib_id, meta_id; 

    /* newclass = {} */ 
    lua_createtable(L, 0, 0); 
    lib_id = lua_gettop(L); 

    /* metatable = {} */ 
    luaL_newmetatable(L, "Foo"); 
    meta_id = lua_gettop(L); 
    luaL_setfuncs(L, _meta, 0); 

    /* metatable.__index = _methods */ 
    luaL_newlib(L, _methods); 
    lua_setfield(L, meta_id, "__index");  

    /* metatable.__metatable = _meta */ 
    luaL_newlib(L, _meta); 
    lua_setfield(L, meta_id, "__metatable"); 

    /* class.__metatable = metatable */ 
    lua_setmetatable(L, lib_id); 

    /* _G["Foo"] = newclass */ 
    lua_setglobal(L, "Foo"); 
} 
3

我试着回答您的解决方案,但显然我没有信誉这么做呢,所以这里去单独回答。

你的解决方案是相当不错的,但它不允许我想做的事情:既有“类似数组”的访问对象,并仍然有功能。看看这个Lua代码:

Foo = {} 

mt = { 
__index = function(table, key) 
    print("Accessing array index ", tostring(key), "\n") 
    return 42 
end 
} 
setmetatable(Foo, mt) 

Foo.bar = function() 
    return 43 
end 

print(tostring(Foo[13]), "\n") 
print(tostring(Foo.bar()), "\n") 

--[[ 
Output: 
Accessing array index 13 
42 
43 
]]-- 

注册使用您的解决方案似乎并没有考虑到这一点的一类,因为__index条目将被覆盖。 对类进行数组访问和函数访问可能没有意义,但为了简单起见(提供一个用于注册这两种类的C函数)我想在任何地方使用相同的代码。有没有人有一个想法如何规避这种限制,以便我可以从C创建一个既有Foo.bar()又有Foo [13]的类?

相关问题