Короче говоря, хотя код, кажется, работает нормально, мне любопытно, существуют ли менее хакерские подходы (чем те, которые я придумал) с *. 1001 *
Предположим, вы создали сопрограмму с помощью lua_newthread , а затем приостановили ее из cclocure с помощью lua_yield . Ваша программа обходит код не-Lua, и теперь пришло время возобновить сопрограмму с помощью lua_resume , но - предположим, что аргументы, предоставленные кодом Lua, крайне недопустимы , и мы должен дать ему ошибку, чтобы указать, что.
Как вы, возможно, знаете, вы не можете вызвать lua_error (или luaL_error ) для состояния, если оно в данный момент не запущено. Таким образом, состояние должно возобновиться, но сразу же возникнет ошибка.
В 5.3 вы должны использовать lua_yieldk , предоставлять функцию продолжения и вызывать там lua_error или luaL_error. Et voilà.
Но, увы, LuaJIT не реализует lua_yieldk, так какие варианты у нас остались?
Одноразовый крючок
Предположим, сообщение об ошибке хранится в char error_text[256]
. Затем мы могли бы связать хук для каждой инструкции непосредственно перед возобновлением,
lua_sethook(L, throw_error, LUA_MASKCOUNT, 1);
int result = lua_resume(L, NULL, ret_count);
, а затем отсоедините крючок и добавьте туда ошибку
void throw_error(lua_State *L, lua_Debug *ar) {
lua_sethook(L, throw_error, 0, 0);
if (error_text == nullptr) return; // trust no one, especially yourself
luaL_error(L, "%s", error_text);
}
Если потребуется очистка строки, вы, конечно, предпочли бы объединить error_text
до luaL_where(L, 1)
перед вызовом _error
, так как lua_error
и luaL_error
делают длинный прыжок и, таким образом, будут последним Ваша функция выполняет.
Упаковщик на стороне Lua
Предположим, вы решили использовать что-то вроде node.js и возобновить ваш код C с парой error, result
, чтобы вы могли иметь функцию-обертку, такую как
function some(arg)
local e, r = some_native(arg)
if (e) then
error(e)
else
return r
end
end
Или, может быть, полностью реорганизовать ваш API, чтобы ошибки также обрабатывались с использованием того же шаблона, но это история для другого дня.
Вариант 1 кажется менее хакерским из двух.
Вариант 2, скорее всего, не вызовет никаких проблем.
Я не могу избавиться от ощущения, что есть намного лучший способ сделать это, что я упускаю из виду (в конце концов, lua_yieldk
- относительно недавнее дополнение).