LINUX.ORG.RU

Вопрос по Lua

 , , ,


0

1

Встраиваю к себе lua после неудачной попытки отыскать встраиваемый C Встроить язык си в программу на языке си ::), всё хорошо через Lua C/API делаю вызовы С функций, через FFI делаю вызовы, из C вызываю функции lua и из lua вызываю С функции вызывающие lua код, короче наигрался. Но вот что я не пойму мы инициализируем lua_State затем загружаем скрипт к примеру luaL_loadfile(L,"./test.lua"); затем исполняем его lua_pcall(L, 0, 1, 0); он отрабатывает, возвращает мне что-то и что я получаю printf("Get script return value => %s\n",lua_tostring(L,-1));, а теперь я исполняю его снова иииии

test2
PANIC: unprotected error in call to Lua API (attempt to call a nil value)

Чуть подробнее C

    lua_State * L = luaL_newstate();
    luaL_openlibs(L);

    int status = luaL_loadfile(L,"./luatest2.lua");
    if(status)
    {
        debug("filed load script: %s ",lua_tostring(L, -1));
    }

    lua_pcall(L, 0, 1, 0);
    lua_pcall(L, 0, 1, 0);

Lua

print("hello");

Выхлоп (вызов только 1 раз, хотя я дёргаю два раза)

hello

Но вспоминаю я ж ничего не возвращаю и не читаю результат возврата и поэтому убираю возвраты

    lua_pcall(L, 0, 0, 0);
    lua_pcall(L, 0, 0, 0);

И получаю выхлоп

hello
PANIC: unprotected error in call to Lua API (attempt to call a nil value)

Я такой репу чешу и вызываю так

   luaL_loadfile(L,"./luatest2.lua");
   lua_pcall(L, 0, 0, 0);
   luaL_loadfile(L,"./luatest2.lua");
   lua_pcall(L, 0, 0, 0);

Выхлоп с двумя «hello» всё верно и ошибки нет.

И вот две вещи которых я недопойму, luaL_loadfile() или остальные функции загрузки кода надо каждый раз вызывать перед lua_pcall? Разве lua_State не хранит текущий кусок кода в себе? Ну и второй вопрос про lua_pcall с 0 параметром возврата это так и надо или нет?

Версия luajit ниже, самосбор, без ключей сборки просто make c си кодом линковка статическая если это важно (статик линковка для проверки возможности вызова функций из lua си функций из самой же программы без загрузки lib.so)

LuaJIT-2.0.5
★★★★★

Последнее исправление: LINUX-ORG-RU (всего исправлений: 7)
Ответ на: комментарий от anonymous

Вот тут к слову у меня ещё вопросы есть

  • 1 Влияет ли на jit компиляцию то что я экспортирую функции не через ffi ,а через api кроме как накладные расходы на вызов появляются. (Ну накладные расходы я сам протестирую)

  • 2 Возможно ли включать и отключать ffi кроме как сборки без и с, ну например софтина может быть клиентом где может быть загружен и исполнен пользовательсткий lua код с ffi тут вся отвецтвенность на пользователе. И оно же может быть сервером куда тоже может быть загружен пользовательский lua (например по сети) но уже без возможности работы с ffi, а то так любой чувак сможет положить сервер раком.

LINUX-ORG-RU ★★★★★
() автор топика
Ответ на: комментарий от LINUX-ORG-RU

1. Апи-стиль не препятствует житу, но он сам решает, когда пора конпелять. Влияет ли на его решение вид враппера апи/ффи - вот этого не знаю.

2. Конечно. Также можно вкл/выкл жит для отдельной функции. http://luajit.org/ext_jit.html

3. На случай если ты еще не видел, есть возможность вызывать луа-функции из сишки без стека (как бы ffi в обратную сторону). Может быть удобно, а может и нет, смотря что пилишь. http://luajit.org/ext_ffi_semantics.html#callback

tl;dr

ffi.cast(myluafunc, ffi.type(“int ()(double)”) -> 
  возвращаешь в сишку, а потом: 
int (*func)(double) = lua_touserdata(L, -1);
int i = func(3.14);
Тут более низкоуровневая типоопасная движуха, и надо внутри myluafunc ловить ошибки pcall()-ом, но бывает удобно при куче несвоих колбеков.

anonymous
()
Ответ на: комментарий от LINUX-ORG-RU

2. Я тут перепутал jit и ffi, уже заметил, но труба позвала и пришлось уйти.

Отключить ffi в рантайме можно, временно удалив его из глобальной таблицы и из registry._PRELOAD/_LOADED, чтобы нельзя было require «ffi». Похожим образом нужно удалить debug, т.к. ffi приедтся временно куда-то сохранить, а это registry, к которой можно добраться через debug.

Более правильный путь это lua sandboxing, см. lua-users wiki, но он и более сложный, придется вкуривать метатаблицы и окружения (это не страшно, просто один раз понять концепцию). В любом случае изолировать фичи от некоторых скриптов возможно, но если речь о безопасности, то делать это нужно очень внимательно.

Также можно создать отдельный привилегированный lua_State, а в обычном удалить debug и ffi (как и os, io, etc) навсегда или вовсе не подключать их, вместо luaL_loadlibs() подключив только нужные библиотеки вручную.

anonymous
()
Ответ на: комментарий от anonymous

На случай если ты еще не видел, есть возможность вызывать луа-функции из сишки без стека (как бы ffi в обратную сторону)

Оверхед большой, будут тормоза. Майк рекомендует вместо коллбеков из C делать poll со стороны Lua.

anonymous
()
Ответ на: комментарий от anonymous

Спасибо большое. Ну, всё основное мне уже известно, буду вникать в детали, недельку поиграюсь, шишки понабиваю, а там уже будет яснее как поступать для рабочих ситуаций.

LINUX-ORG-RU ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.