Question :
How do I access and set a variable from a class made in C ++ to Lua?
// C++
#ifndef SCRIPTSTORAGE_H
#define SCRIPTSTORAGE_H
#include "HTest.h"
#include <luajit/lua.hpp>
#include <iostream>
struct HObject {
unsigned int id;
std::string name;
float x, y, z;
float sx, sy, sz;
float u, v;
HObject()
{
id = 1;
}
};
static bool checkFunctionArgs(lua_State* ls, const char* fname, unsigned int nargs)
{
int fnargs = lua_gettop(ls) - 1;
if(fnargs < (int)nargs)
{
std::cout << "LuaScriptError: " << fname << "() need at least %d parameter(" << nargs << ")n" << std::endl;;
return true;
}
if(fnargs > (int)nargs)
{
std::cout << "LuaScriptError: " << fname << "() takes " << nargs << " positional arguments but " << fnargs << " were given" << std::endl;
return true;
}
return false;
}
HObject* HObject_check(lua_State* ls, int index)
{
void* ud = 0;
luaL_checktype(ls, index, LUA_TTABLE);
lua_getfield(ls, index, "__self");
ud = luaL_checkudata(ls, index, "HObject:new");
luaL_argcheck(ls, ud != 0, 0, "'HObject:new' expected");
return *((HObject**)ud);
}
static int HObject_newHObject(lua_State* ls)
{
if(checkFunctionArgs(ls, "HObjec:new", 0)){
return 0;
}
luaL_checktype(ls, 1, LUA_TTABLE);
lua_newtable(ls);
lua_pushvalue(ls, 1);
lua_setmetatable(ls, -2);
lua_pushvalue(ls, 1);
lua_setfield(ls, 1, "__index");
HObject** obj = (HObject**)lua_newuserdata(ls, sizeof(HObject*));
*obj = new HObject();
luaL_getmetatable(ls, "HObject:new");
lua_setmetatable(ls, -2);
lua_setfield(ls, -2, "__self");
return 1;
}
static int HObject_destructor(lua_State* ls)
{
HObject* obj = HObject_check(ls, 1);
delete obj;
return 1;
}
void HTest_register(lua_State* ls)
{
static const luaL_Reg hobjec_funcs[] = {
{"new", HObject_newHObject},
{"__gc", HObject_destructor},
{NULL, NULL}
};
luaL_newmetatable(ls, "HObject:new");
luaL_register(ls, 0, hobjec_funcs);
lua_pushvalue(ls, -1);
lua_setfield(ls, -2, "__index");
luaL_register(ls, "HObject", hobjec_funcs);
}
#endif // SCRIPTSTORAGE_H
-- Lua
local obj = HObject:new() -- OK
obj.variavel = 10 -- Exemplo de escrever na variável
print(obj.variavel) -- Exemplo de acessar variável
I want to access and write in the variable, but I do not know how to link the same in Lua. I have already managed to link the class HOBject
along with its functions,
Answer :
There is no standard way of establishing variable access in LUA. You have two options to work around this:
Getter and Setters
The first one is easier, but it may seem kind of ugly. You can create getters and setters. So you would have to create a get and set pair for each variable you want to have accessible, for example:
static int getVariavel(lua_State* ls)
{
//Obter seu objeto aqui
lua_pushinteger(ls, obj->variavel);
return 1;
}
static int setVariavel(lua_State* ls)
{
//Obter seu objeto aqui
obj->variavel = lua_tointeger(ls, -1);
lua_pop(1);
return 0;
}
You have to create a pair of these for each variable, but this can be simplified with the help of macros and / or templates. With this template you can access and change the variables as follows:
local obj = HObject:new() -- OK
obj:setVariavel(10) -- Exemplo de escrever na variável
print(obj:getVariavel()) -- Exemplo de acessar variável
Filtering by __index
__newindex
The other way would be to place handlers for the __index
and __newindex
events in the metatable of the objects. So you could filter the variable names and return their values:
static int index(lua_State *ls)
{
///Obter objeto aqui.
string s = lua_tostring(ls, 2);
if(s == "variavel")
lua_pushinteger(ls, obj->variavel);
else if(s == "variavel2")
lua_pushinteger(ls, obj->variavel2);
// Outras variáveis aqui.
else
{
//Chamar a table com as funções.
}
return 1;
}
static int newIndex(lua_State *ls)
{
//Obter objeto aqui
string s = lua_tostring(ls, 2);
if(s == "variavel")
obj->variavel = lua_tointeger(ls, -1);
else if(s == "variavel2")
obj->variavel2 = lua_tointeger(ls, -1);
//..outras variáveis aqui.
else
//Mostrar msg de erro dizendo que tal variável não existe.
}
This model needs only these two functions, but comparing strings one by one can be slow if you have a very large number of attributes and your class. On the other hand, access on Lua looks more beautiful, in my opinion:
-- Lua
local obj = HObject:new() -- OK
obj.variavel = 10 -- Exemplo de escrever na variável
print(obj.variavel) -- Exemplo de acessar variável