D / Dlang: интерфейс Lua, есть ли способ заставить пользователей не иметь доступа к промежуточным объектам? - PullRequest
1 голос
/ 06 мая 2019

Статус: вроде решено.Переключение Lua.Ref (близкого к LuaD LuaObject) на структуру, как было предложено в ответе, решило большинство проблем, связанных с освобождением ссылок, и я вернулся к аналогичному механизму, который использует LuaD.Подробнее об этом в конце.


В одном из моих проектов я работаю с интерфейсом Lua.В основном я позаимствовал идеи у LuaD.Механизм в LuaD использует lua_ref & lua_unref, чтобы иметь возможность перемещать ссылки на таблицы / функции lua в пространстве D, но это вызывает серьезные проблемы, потому что вызовы деструкторов и их порядок не гарантируются.LuaD обычно вызывает ошибки по крайней мере при выходе из программы.

Поскольку кажется, что LuaD больше не поддерживается, я решил написать свой собственный интерфейс для своих целей.Мой класс интерфейса Lua находится здесь: https://github.com/mkoskim/games/blob/master/engine/util/lua.d

Примеры использования можно найти здесь: https://github.com/mkoskim/games/blob/master/demo/luasketch/luademo.d

А в случае необходимости скрипт Lua, используемый примером, находится здесь: https://github.com/mkoskim/games/blob/master/demo/luasketch/data/test.lua

Интерфейс работает следующим образом:

  • Lua.opIndex помещает глобальную таблицу и индексный ключ в стек и возвращает объект Top.Например, lua["math"] помещает в стек _G и "math".

  • Дальнейший доступ осуществляется через объект Top.Top.opIndex идет глубже в иерархии таблиц.Другие методы (call, get, set) являются «финальными» методами, которые выполняют операцию с таблицей и ключом наверху стека, а затем очищают стек.


Закрыть все работает нормально, за исключением того, что этот механизм имеет неприятную причуду / ошибку, которую я не знаю, как ее решить.Если вы не вызовете ни один из этих «финальных» методов, Top оставит таблицу и ключ в стеке:

lua["math"]["abs"].call(-1); // Works. Final method (call) called.
lua["math"]["abs"];          // table ref & key left to stack :(

Что я точно знаю, так это то, что игра с деструктором Top () не работает, поскольку он не вызывается сразу, когда на объект больше не ссылаются.

ПРИМЕЧАНИЕ. Если есть какой-то оператор, который вызывается при обращении к объекту как rvalue, я мог бы заменить call (), set () иМетоды get () с перегрузками операторов.

Вопросы:

  1. Есть ли способ запретить пользователям писать такие выражения (получение объекта Top без вызова "final")методы)?Я действительно не хочу, чтобы пользователи писали, например, luafunc = lua["math"]["abs"], а потом пытались позвонить, потому что это не будет работать вообще.Не без того, чтобы начать играть с lua_ref & lua_unref и начать бороться с теми же проблемами, что и LuaD.

  2. Есть ли какая-либо перегрузка оператора opAccess, то есть перегрузка того, что происходит при использовании объектакак значение?То есть выражение "a = b" -> "a.opAssign (b.opAccess)"?opCast не работает, он вызывается только с явными приведениями.


Есть еще предложения?Я внутренне чувствую, что ищу решение с неправильной стороны.Я чувствую, что проблема заключается в сфере метапрограммирования: я пытаюсь «охватить» вещи на уровне выражений, что, по моему мнению, не подходит для классов и объектов.

До сих пор я пытался сохранитьLuaD смотрит на интерфейс пользователя на стороне пользователя, но я думаю, что если бы я мог изменить интерфейс на что-то вроде следующего, я мог бы заставить его работать:

lua.call(["math", "abs"], 1);          // call lua.math.abs(2)
lua.get(["table", "x", "y", "z"], 2);  // lua table.x.y.z = 2
...

Синтаксически, который обеспечил бы эту ссылку на luaобъект, выбранный посредством индексации, наконец используется для чего-то в выражении, и стек будет очищен.


UPDATE: Как уже говорилось, изменение Lua.Ref для структурирования решаемых проблем, связанных сразыменование, и я снова использую механизм ссылок, похожий на LuaD.Я лично чувствую, что этот механизм соответствует синтаксису в стиле LuaD, который я использую, и это может быть довольно сложной задачей для правильной работы синтаксиса с другими механизмами.Я все еще открыт, чтобы услышать, есть ли у кого-то идеи, чтобы заставить его работать.

Система, которую я набросал для замены ссылок (для решения проблемы с объектами, содержащими ссылки, живущие дольше, чем песочница lua), вероятно, потребовала бы другой вид интерфейса, что-то похожее я набросал выше.

1 Ответ

1 голос
/ 06 мая 2019

У вас также есть проблема, когда люди делают

auto math_abs = lua["math"]["abs"];

math_abs.call(1);
math_abs.call(3);

Это удвоит поп.

Сделать Top структурой, которая содержит индекс стека того, на что они ссылаются. Таким образом, вы можете использовать его известное поведение определения объема и уничтожения в ваших интересах. Убедитесь, что вы правильно обрабатываете this(this).

Только появляется в деструкторе, когда значение является фактическим верхним значением. Вы можете использовать набор битов в LuaInterface, чтобы отслеживать, какие позиции стека используются, и помещать в него значения, используя lua_replace, если вас беспокоит чрезмерное использование стека.

...