Как вывести скрипт lua в C
Это работает, когда lua вызывает C API, если функция C вызывает функцию lua, и lua вызывает функцию C API, ошибка longjmp
lua_yieldk, lua_callk и lua_pcallk как это работает?
мой код c:
int trace(lua_State *L)
{
const char *str = luaL_checkstring(L, 1);
printf("%d:%s\n", GetTickCount(), str);
return 1;
}
int pause(lua_State *L)
{
printf("pause");
return lua_yield(L, 0);
}
int _tmain(int argc, _TCHAR* argv[])
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_pushcfunction( L, pause );
lua_setglobal( L, "pause" );
lua_pushcfunction( L, trace );
lua_setglobal( L, "trace" );
if (luaL_loadfile(L, "test.lua"))
error(L, "cannot run script %s\n", lua_tostring(L,-1));
lua_resume(L, NULL, 0);
lua_getglobal(L, "t");
lua_pcallk(L, 0, 0, 0, 0, 0);
lua_resume(L, NULL, 0);
lua_resume(L, NULL, 0);
lua_resume(L, NULL, 0);
lua_resume(L, NULL, 0);
lua_close(L);
getchar();
return 0;
}
код Луа
function t()
pause(2)
pause(2)
pause(2)
pause(2)
end
1 ответ
Вы вызываете lua_resume для потока, возвращаемого lua_newthread
не lua_newstate
,
Таким образом, в вашем коде вам придется либо изменить первый lua_resume
в lua_(p)call
:
if (luaL_loadfile(L, "test.lua"))
error(L, "cannot run script %s\n", lua_tostring(L,-1));
lua_pcall(L, 0, 0, 0);
или поменяться luaL_loadfile
за luaL_dofile
:
if (luaL_dofile(L, "test.lua"))
error(L, "cannot run script %s\n", lua_tostring(L,-1));
//lua_resume(L, NULL, 0); Not necessary anymore
Я не имею отношения к эффективности установки глобального t
Вот.
Теперь к основному вопросу вопроса:
- Во-первых, каждый звонок
lua_callk
,lua_pcallk
или жеlua_yieldk
должен получить функцию продолжения в качестве аргумента. В вашем случае это 0. На самом деле,lua_yieldk
может принимать 0 как функцию продолжения, но затем управление передается обратно в скрипт Lua, где происходит вызов функции C. - Затем любой вызов этих функций должен выполняться в потоке сопрограммы, а не в основном потоке.
- И, наконец, вы не можете уступить через границу C-вызовов. То есть когда звонишь
lua_pcallk
и порция, которую вызывает pcallk, приводит к выполнению функции продолжения. Тем не менее, вы не можете иметьlua_pcallk
вызвать функцию Lua, которая в свою очередь вызывает функцию C, которая дает (pause
в твоем примере). Это запрещено.
Пример lua_pcallk
:
int cont(lua_State *L)
{
getchar();
return 0;
}
int pcallktest(lua_State *L)
{
luaL_loadstring(L, "yield()");
int test = lua_pcallk(L, 0, 0, 0, 0, cont);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_State *T = lua_newthread(L);
luaL_loadfile(T, "Test.lua");
lua_pushcfunction(T, pcallktest);
lua_resume(T, NULL, 1);
return 0;
}
Код Lua:
local pcallktest = ...
pcallktest()
Теперь этот фрагмент кода запускает новую сопрограмму из файла "Test.lua". Код Lua вызывает функцию C pcallktest
который в свою очередь вызывает lua_pcallk
на другой функции Lua, которая просто дает. Когда происходит выход, выполнение переходит (longjmp) к cont
функция, которая была предоставлена в качестве аргумента lua_pcallk
, Когда cont
функция возвращается, выполнение сопрограммы заканчивается и lua_resume
от _tmain
возвращается.
Пример lua_yieldk
:
int cont(lua_State *L)
{
getchar();
return 0;
}
int yieldktest(lua_State *L)
{
return lua_yieldk(L, 0, 0, cont);
}
int _tmain(int argc, _TCHAR* argv[])
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_State *T = lua_newthread(L);
luaL_loadfile(T, "Test.lua");
lua_pushcfunction(T, yieldktest);
lua_resume(T, NULL, 1);
lua_resume(T, NULL, 0);
return 0;
}
Код Lua:
local yieldktest = ...
yieldktest()
Этот бит в свою очередь выполняет сопрограмму, которая дает изнутри функцию C (yieldktest
). Когда сопрограмма затем возобновляется (второй lua_resume
) управление передается обратно в функцию продолжения cont
, который выполняется как продолжение yieldktest
,
Эти примеры не имеют дело с lua_getctx
и складывать состояния, но просто демонстрировать механизмы этих функций.