2010-07-26 13 views
8

Mam kilka klas w C++, które chciałbym pokazać Lua. Mogę zadzwonić pod numer Widget:New(), aby uzyskać powrót userdata z metatabilnym zbiorem do tabeli WidgetMeta. WidgetMeta posiada wszystkie funkcje C++ w nim, i to __index jest ustawione do siebie, więc mogę to zrobić:Traktowanie daty użytkownika jak tabeli w Lua

w = Widget:New() 
w:Foo() -- Foo is defined in C code 

To wszystko dość proste.

Oto część, której nie mogę rozgryźć. Chcę móc umieścić zdefiniowane przez Lua zmienne i funkcje na moich danych użytkownika tak, jakby były tabelą. Nie można tego zrobić oczywiście w sposób oczywisty. Nie mogę go upuścić na podstawie danych użytkownika, ponieważ chcę, aby był on unikalny dla każdej z danych użytkownika.

w1 = Widget:New() 
w2 = Widget:New() 

function w1:Bar() print "Hello!" end -- Both functions unique 
function w1:Baz() print "World!" end -- to their own userdata 

Mój obecny plan ataku jest mieć metatable mają specjalną tabelę na to, że mapuje między UserData i stołem, gdzie można przechowywać funkcje i zmienne za-userdata. Problem polega na tym, że nie jestem pewien, jak najlepiej to zrobić, lub czy istnieje lepsze rozwiązanie. więc moje pytanie jest dwojakie: kiedy konfiguruję metamodulacje __index i __newindex, czy zapisuję je w kodzie Lua w pliku tekstowym i uruchamiam, zanim uruchomię resztę, lub umieszczę kod Lua bezpośrednio z C ciąg w moim programie przez luaL_loadstring, czy robię to z interfejsem C i radzę sobie ze wszystkimi manipulacjami stosu? i po drugie, jak mam napisać tę funkcję ... ale poradzę sobie z tym, kiedy już zdecyduję, która jest najlepsza droga.

+1

jsimmons' jest doskonała dla Lua 5.1 i wcześniej, ale w Lua 5.2, można skojarzyć z każdej tabeli UserData użyciu lua_setuservalue i pobrać go za pomocą lua_getuservalue. Tak więc odpowiedź 5.2 byłaby podobna do tej z jsimmons "używając tych nowych skojarzeń tabel zamiast środowisk funkcjonalnych. –

Odpowiedz

9

Dodaj środowisko funkcji do danych użytkownika i przekieruj dostęp przez to.

Oto mój stary kod opisujący proces.

static int l_irc_index(lua_State* L) 
{ 
    /* object, key */ 
    /* first check the environment */ 
    lua_getfenv(L, -2); 
    lua_pushvalue(L, -2); 
    lua_rawget(L, -2); 
    if(lua_isnoneornil(L, -1) == 0) 
    { 
     return 1; 
    } 

    lua_pop(L, 2); 

    /* second check the metatable */  
    lua_getmetatable(L, -2); 
    lua_pushvalue(L, -2); 
    lua_rawget(L, -2); 

    /* nil or otherwise, we return here */ 
    return 1; 
} 

static int l_irc_newindex(lua_State* L) 
{ 
    /* object, key, value */ 

    lua_getfenv(L, -3); 
    lua_pushvalue(L, -3); 
    lua_pushvalue(L, -3); 
    lua_rawset(L, -3); 

    return 0; 
} 
+0

Dzięki, to było znacznie czystsze niż miałem zamiar spróbować: D – Alex