Я использую оболочку C ++ вокруг библиотеки libluajit-5.1-dev
Здесь
Мои данные существуют как экземпляр структуры C ++. Я не могу изменить этот дизайн. Эти данные постоянно меняются
Я хочу выполнить некоторые предикатные проверки этих данных, которые можно добавить с помощью языка сценариев Lua.
Я понимаю, как добавлять и выполнять функции в Lua, но я сталкиваюсь с битой, ссылающейся на данные C ++ из Lua, а не просто копирую данные C ++ в Lua.
Например:
struct MyData {
int a = 1;
int b = 2;
}
MyData data;
ctx.writeVariable("a", data.a);
std::cout << ctx.readVariable<int>("a") << std::endl; // prints 1
data.a = 3;
std::cout << ctx.readVariable<int>("a") << std::endl; // still prints 1 (obviously). I want this to print 3
Один из способов заставить это работать - хранить указатели C ++ в стеке Lua, например,
LuaContext ctx;
MyData foo;
ctx.writeVariable("a",&foo.a);
std::cout << *ctx.readVariable<int*>("a") << std::endl; //prints 1
foo.a = 42;
std::cout << *ctx.readVariable<int*>("a") << std::endl; //prints 42. Yay
Но теперь я не могу использовать переменные Lua в функциях Lua (в качестве значения) , поскольку в Lua.
отсутствует понятие «разыменование». Одно из решений, которое я нашел, - написать функцию, которая определяет новый Lua Тип обтекания std::reffrence_wrapper<T>
, а затем использовать список захвата лямбды, переданный зарегистрированной функции «getter». Это лучше объясняется в комментариях к приведенному ниже коду:
template<typename T>
void registerRefferenceType(LuaContext& ctx, std::string name, const std::reference_wrapper<T>& refference) {
ctx.registerMember<T(std::reference_wrapper<T>::*)>(
"value", //adds a member item (called value) to the Lua type std::reference_wrapper<T>
//This is called when lua code wants to read the variable
[&refference](const std::reference_wrapper<T>&) -> T { return refference.get(); },
//This is called when lua code wants to write the variable
[](std::reference_wrapper<T>&, int) {});
//Push the std::reference_wrapper<T> onto the lua stack, with name <name>. The value of this reffernce can be retrieved with <name>.value
ctx.writeVariable(name,refference);
}
Теперь, если я это сделаю:
LuaContext ctx;
int a = 9;
auto ref = std::reference_wrapper(a);
registerRefferenceType(ctx, "a", ref);
std::cout << ctx.executeCode<int>("return a.value") << std::endl; //prints 9
a = 10;
std::cout << ctx.executeCode<int>("return a.value") << std::endl; //prints 10
Это работает так, как я хочу. Но это кажется немного хакерским. Есть ли лучший способ или "стандартный" способ ссылки на переменные C ++ из Lua?
Спасибо
edit: одна проблема с моим решением заключается в том, что если переменная C ++ выходит из области видимости, он все еще будет существовать в Lua и будет просто давать значения мусора. Я думаю, что это должно быть хорошо, но если есть лучший способ, я хотел бы знать