gpt4 book ai didi

lua - 如何在 C 函数中生成 lua 脚本

转载 作者:行者123 更新时间:2023-12-04 20:42:30 25 4
gpt4 key购买 nike

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

lua代码

function t()
pause(2)
pause(2)
pause(2)
pause(2)
end

最佳答案

您在 lua_newthread 而不是 lua_newstate 返回的线程上调用 lua_resume。

因此在您的代码中,您要么必须将第一个 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_callklua_pcallklua_yieldk 都需要接收一个延续函数作为参数。在你的情况下它是 0。实际上,lua_yieldk 可以将 0 作为延续函数,但随后控制权将传递回 Lua 脚本,在该脚本中调用 C 函数。
  • 接下来,对这些函数的任何调用都必须在协程线程中进行,而不是在主线程中进行。
  • 最后,您不能跨越 C 调用边界让步。也就是说,当您调用 lua_pcallk 并且 pcallk 正在调用的 block 产生时,将执行延续函数。但是,您不能让 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,该函数仅产生。当 yield 发生时,执行跳转 (longjmp) 到 cont 函数,该函数作为参数提供给 lua_pcallk。当 cont 函数返回时,协程执行结束,_tmain 中的 lua_resume 返回。

一个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 和堆栈状态,而只是演示这些函数的机制。

关于lua - 如何在 C 函数中生成 lua 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16416711/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com