Обращение с userdate как с таблицей в Lua

у меня есть некоторые классы на C++, которые я хотел бы предоставить Lua. Я могу позвонить Widget:New() чтобы получить возврат пользовательских данных с набором метатаблиц в таблице WidgetMeta. WidgetMeta имеет все функции C++ в нем, и это __index настроен на себя, поэтому я могу сделать это:

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

это все довольно просто.

теперь вот часть, которую я не могу понять. Я хочу иметь возможность помещать определенные Lua переменные и функции в мой userdata, как если бы это была таблица. Это невозможно. прямо очевидно. Я не могу бросить его на userdata, потому что я хочу, чтобы он был уникальным для userdata.

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

мой текущий план атаки состоит в том, чтобы у metatable была специальная таблица, которая отображает между userdata и таблицей, где я могу хранить функции и переменные per-userdata. Проблема в том, что я не уверен, как лучше всего это сделать, или есть ли лучшее решение. поэтому мой вопрос двоякий: когда я настраиваю свой _ _ index и _ _ newindex metamethods, я пишу они в коде Lua в текстовом файле и запускают его перед запуском остальной части материала, или я помещаю код Lua непосредственно из строки C в свою программу через luaL_loadstring, или я делаю это с интерфейсом C и имею дело со всеми манипуляциями стека? и во-вторых, как мне написать эту функцию... но я разберусь с этим, как только решу, какой маршрут лучше выбрать.

2 ответов


добавьте функциональную среду в userdata и перенаправьте доступ через нее.

вот мой старый код, который описывает этот процесс.

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;
}

вы действительно должны взглянуть на tolua++, который имеет очень похожие концепции. Все объекты userdata, созданные из lua, имеют скрытую таблицу для хранения своих свойств.

этот раздел руководства описывает его : http://www.codenix.com / ~tolua / tolua++.html#дополнительно