Столкнулся с проблемой. Нужно вставить в таблицу, в луа C-функцию, которая должна обращаться к НЕ статичному полу (экземпляру класса). Пробовал использовать лямбды, но не получается привести их к lua_CFunction. Как можно это реализовать?
class Computer {
private:
lua_State *luaState;
public:
void run() {
luaState = luaL_newstate();
lua_createtable(luaState, 0, 1);
lua_pushcfunction(luaState, /* ?? */);
lua_setfield(luaState, -2, "test");
lua_setglobal(luaState, "computer");
}
}
Computer *c = new Computer;
c.run();
Поскольку вы создаёте lua_State
внутри вашего объекта, то можно сохранить указатель на объект в таблице, внутри Lua и использовать его для вызова методов. При этом, для каждого метода, который вы хотите вызвать из Lua, вам придётся писать Си-обёртку, которая будет извлекать этот указатель из таблицы и вызывать соответствующий метод.
Например, если вам надо вызвать такой метод:
void Computer::test(int i) {
std::cout << "test: " << i;
}
то, вы сохраняете указатель на объект в конструкторе:
Computer::Computer(void) {
luaState = luaL_newstate();
luaL_openlibs( luaState );
lua_createtable(luaState, 0, 2);
// указатель на объект
lua_pushlightuserdata(luaState, this);
lua_setfield(luaState, -2, "_self");
// указатель на функцию обёртку
lua_pushcfunction(luaState, test_wrap);
lua_setfield(luaState, -2, "test");
lua_setglobal(luaState, "computer");
}
.. и пишите обёртку:
int test_wrap(lua_State *L)
{
// чтение аргумента(ов) функции
if(!lua_isnumber(L, -1))
luaL_error(L, "Expected a Number as a first argument!");
int i = lua_tonumber(L, -1);
// загрузка указателя
Computer * pComp = get_obj_pointer(L);
// вызов метода
if (pComp) {
pComp->test(i);
}
return 0;
}
Функция чтения указателя на объект из луа-таблицы:
Computer * get_obj_pointer(lua_State *L)
{
lua_getglobal(L, "computer");
if (!lua_istable(L, -1))
luaL_error(L, "Table 'computer' is not found!");
lua_pushstring(L, "_self");
lua_gettable(L, -2);
if (!lua_isuserdata(L, -1))
luaL_error(L, "Value 'computer._self' is not found!");
void *p = lua_touserdata(L, -1);
lua_pop(L, 1);
return (Computer *) p;
}
Далее, пишите тестовый скрипт script.lua
:
local comp = computer
print(comp._self) # напечатает "userdata 0xXXXXXX"
print(comp.test(15)) # напечатает "test: 15"
и вызываете его в методе run
:
void Computer::run(void) {
int err = luaL_dofile(luaState, "script.lua");
if (err) {
std::cout << "Error: " << lua_tostring(luaState, -1);
lua_pop(luaState, 1);
}
}
Тестовый код целиком: https://pastebin.com/FSdsRaAd
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Виртуальный выделенный сервер (VDS) становится отличным выбором
Добрый день, хочу использовать в своём проекте на QT510 преключатель из примера
Можно ли, задав в структуре std::tm нужную дату и время, получить значение в миллисекундах от начала отсчёта времени, те
Когда в eclipse'е я создал свежий проект, то он сразу выдаёт ошибки и это связанно с тем, что eclipse не импортировал javafxЯ устанавливал e(fx)clipse и делал:
Всем добрый деньК примеру есть у меня лишь интерфейс, без реализации каким-либо классом