Как вывести скрипт 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 и складывать состояния, но просто демонстрировать механизмы этих функций.

Другие вопросы по тегам