В C вы не можете обращаться к функциям Lua напрямую, но можете представлять числа и строки. Итак, чтобы функция "вызывалась позже", можно хранить эту функцию в какой-нибудь таблице и обращаться к ней по числовому или строковому ключу таблицы.
Вот простой механизм для начала:
На стороне Луа:
funcs = {}
local function register_hanlder(key, fn)
funcs[key] = fn
end
register_handler("on_mouse_click", function()
print "You clicked me!"
end)
На стороне С:
/* code not tested */
lua_getglobal(L, "funcs");
lua_getfield(L, -1, "on_mouse_click");
if (!lua_isnil(L, -1)) {
lua_call(L, 0, 0);
else {
// nothing registered
}
Вместо регистрации функций в глобальной таблице вы можете зарегистрировать их в таблице реестра (см. luaL_ref). Вы получите некоторое целое число (это ключ в таблице реестра, где находится значение функции), которое вы можете передать в своем коде C.
Обратите внимание, что если вам не нужно хранить функцию Lua «для использования позже», вам не нужно ничего из этого: если ваша функция C имеет какую-то функцию Lua, переданную ей через аргумент, вы можете вызвать ее напрямую.
== Изменить:
Как я уже упоминал, вместо использования глобальной переменной (funcs
выше) вы можете хранить ссылку на функцию в «реестре». Концептуально нет никакой разницы между этим методом и предыдущим.
Давайте воспользуемся предыдущим примером: вы хотите, чтобы программист Lua мог зарегистрировать функцию, которая будет запускаться при каждом щелчке мыши в вашем приложении.
Сторона Lua будет выглядеть так:
register_mouse_click_handler(function()
print "the mouse was clicked!"
end)
На стороне C вы определяете register_mouse_click_handler
:
static int the_mouse_click_handler = 0;
static int register_mouse_click_handler(lua_State* L) {
the_mouse_click_handler = luaL_ref(L, LUA_REGISTRYINDEX);
return 0;
}
(... и открыть его для Lua.)
Затем в вашем приложении, когда вы щелкаете мышью и хотите вызвать функцию Lua, вы делаете:
...
if (the_mouse_click_handler != 0) {
lua_rawgeti(L, LUA_REGISTRYINDEX, the_mouse_click_handler);
lua_call(L, 0, 0);
} else {
// No mouse handler was registered.
}
...
(Могут быть опечатки в коде.)
person
Niccolo M.
schedule
22.05.2014