У меня есть объекты в моей C ++ программе, которые я передаю Lua как userdata, и я переопределяю метатаблицу для этих userdata, так что присваивание и из индексов объекта (через __newindex и __index) приводит к вызову C, который преобразует назначение воздействовать на объект C ++ или преобразовывать элемент C ++ в значение Lua (либо другие пользовательские данные, либо базовый тип, такой как bool, number, string). Пользовательские данные передаются в качестве аргументов для событийных функций Lua, которые вызываются из моей программы на C ++.
luaL_newmetatable(L, "object");
lua_pushstring(L, "__index");
lua_pushvalue(L, -2); /* pushes the metatable */
lua_settable(L, -3); /* metatable.__index = metatable */
luaL_openlib(L, NULL, vallib_m, 0);
luaL_openlib(L, "internal", vallib_f, 0);
lua_pushstring(L, "__index");
lua_pushstring(L, "get");
lua_gettable(L, 2); /* get val.get */
lua_settable(L, 1); /* metatable.__index = val.get */
lua_pushstring(L, "__newindex");
lua_pushstring(L, "set");
lua_gettable(L, 2); /* get array.set */
lua_settable(L, 1); /* metatable.__newindex = val.set */
Однако это не позволяет мне присваивать саму фактическую переменную, только индекс переменной. Нет мета-события для прямого переопределения оператора присваивания, поэтому я ищу обходной путь.
Другими словами, я могу сделать это: lua_userdata_object_passed_as_arg_to_event["is_it_true"]=true
и он присваивает логическое значение Lua моему внутреннему объекту C ++, но если я сделаю это:
lua_userdata_object_passed_as_arg_to_event = new_object()
это изменит то, на что ссылается переменная Lua, но, как я понимаю, ничего не изменит с основным объектом.
Один из обходных путей, который я рассмотрел, — это взлом, требующий от разработчиков lua_userdata_object_passed_as_arg_to_event["__self"] = new_object()
если они хотят изменить сам объект, но это нежелательно.
Итак, я нашел несколько уникальных решений для переопределения оператора присваивания с помощью глобальных переменных и переопределения глобальных метатабельных операторов присваивания, но я хочу посмотреть, сможет ли кто-нибудь помочь мне объяснить это решение. Увидеть http://lua-users.org/lists/lua-l/2012-01/msg00413.html а также https://www.lua.org/pil/14.2.html.
В частности, мои переменные являются аргументами функций, а не глобалами, так как я могу преобразовать в глобальные переменные через C API, чтобы любые назначения были захвачены пользовательской функцией C, которая будет действовать, если назначение происходит с глобальными пользовательскими данными?
Кстати, мои пользовательские данные — это указатель на объект, чтобы избежать дублирования больших объектов, если это имеет значение.
Lua и C / C ++ — это разные языки с разными потребностями. В C / C ++ переменная всегда ссылается на конкретный объект. Вы можете изменить содержимое этого объекта, но вы никогда не сможете заключить переменную с другим объектом. Если вы делаете a = b;
, вы копируете значение b
в a
, Вы никогда не можете изменить какой объект a
говорит о.
В Lua переменные не постоянно ссылаться на что угодно. Таким образом, существует различие между объектом, который в данный момент хранится в переменной, и значением этого объекта.
Ваш Kludge через функции глобальных переменных, но local
переменные — это вещи, которые на самом деле не существуют. Они локации в стеке Lua; вы не можете переопределить поведение Lua по умолчанию в отношении них.
Лучший способ справиться с этим — принимать разница между C и Lua. Пишите код на Lua так, как вы пишете код на Lua. Не пытайтесь заставить код Lua работать как C; это глупость. Это разные языки, и вы должны учитывать их различия, а не работать против них.
Если вы хотите дать Lua возможность сделать эквивалент a = b
, то вы должны создать функцию в вашем типе под названием assign
или что-то, что позволит вам присвоить значение объекта. Точно так же, как если вы хотите скопировать все элементы таблицы из одной таблицы в другую, вам нужно написать функцию для этого.
Других решений пока нет …