2012-06-19 115 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]的類?

相關問題