Поп-функции аргументы в Lua CFunction безопасно - PullRequest
1 голос
/ 01 мая 2019

Я работаю над очень большой структурой, предоставляющей множество алгоритмов, функций и возможностей от C / C ++ до Lua. Эта структура также предоставляет некоторые функциональные возможности, которые работают с таблицами, индексаторами и часто являются просто прокси-сервером для поведения по умолчанию, если определенное условие не выполняется.

Мой вопрос очень простой; Безопасно ли извлекать аргументы функции из функции C, т. Е. Реализации newindex в C? В настоящее время я реализую его, получив объект, который должен содержать ключ и значение, и вставив его перед ключом и значением, предоставленными метаметоду __newindex. Затем я использую lua_rawset, чтобы установить его для объекта, который я поместил перед собой, выталкивая два аргумента функции. Это безопасно?

Я провел обширные тесты, включая тесты на контрольных стеках и мониторинг вершины стека Lua. Ни один из этих тестов не является для меня достаточно убедительным, мне бы хотелось узнать мнение других разработчиков Lua.

Я прочитал много частей документации Lua, однако, кажется, нет четкого заявления об этом (или я не нашел его). В руководстве (https://www.lua.org/manual/5.3/manual.html#lua_CFunction) указано:

Любое другое значение в стеке ниже результатов будет корректно отброшено Lua.

Однако это не отвечает на мой вопрос, если отбрасывание этих значений само по себе может вызвать проблемы.

// An example, is this safe to do? My guts say yes
int lm_entity__newindex(lua_State* L) {
    luaL_checkany(L, 1); // udata
    luaL_checkany(L, 2); // key
    luaL_checkany(L, 3); // value 

    // does not manipulate the stack, merely casts lua_touserdata
    auto entity = lm_entity(L, 1);

    // get the members table 
    lua_rawgeti(L, LUA_REGISTRYINDEX, entity->members_ref);

    // place before key and value (lua_rotate)
    lua_insert(L, -3);

    // store, in turn popping the two function arguments
    lua_rawset(L, -3);

    // pop members table
    lua_pop(L, 1);

    return 0;
}

Я ожидаю, что это будет работать безопасно, потому что при вызове функции стек восстанавливается впоследствии на основе количества параметров, переданных функции, и количества возвращаемых значений, помещенных в стек. Однако я не уверен, что выталкивание двух аргументов из стека вызовет проблемы в этом отношении, хотя мое тестирование, похоже, доказывает обратное.

...