当lua调用C API时它会起作用 如果一个C函数调用lua函数,并且lua函数调用C API,则longjmp错误
lua_yieldk,lua_callk和lua_pcallk 它是如何工作的?
我的代码:
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;
}
lua代码
function t()
pause(2)
pause(2)
pause(2)
pause(2)
end
答案 0 :(得分:6)
您在lua_newthread
返回的主题上调用lua_resume,而不是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函数的调用。lua_pcallk
并且pcallk正在调用yield的块时,将执行continuation函数。但是,您不能让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函数上的lua_pcallk
。当产量发生时,执行跳转(longjmp)到cont
函数,该函数作为lua_pcallk
的参数提供。当cont
函数返回时,协程执行结束,lua_resume
的{{1}}返回。
_tmain
的一个例子:
lua_yieldk
Lua代码:
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;
}
该位依次执行从C函数(local yieldktest = ...
yieldktest()
)内产生的协同程序。当协程恢复后(第二个yieldktest
),控制权将传递回继续函数lua_resume
,该函数作为cont
的延续执行。
这些示例不涉及yieldktest
和堆栈状态,而只是演示这些函数的机制。