Tenho o seguinte script lua, no qual uso uma função C++ que precisa ler chaves e valores de uma tabela aninhada:
local scenariolist = {
scenarios = {
'scenario1',
'scenario3',
'scenario2'
},
result = true,
message = 'test message'
}
my.sendfromscenariolist(scenariolist)
Esta é minha função C++ que é executada ao chamar sendfromscenariolist
:
int ScenarioFunction(lua_State* L) {
int nargs = lua_gettop(L);
if (nargs != 1) {
return 0;
}
int type = lua_type(L, 1);
if (type != LUA_TTABLE) {
return 0;
}
ParseScenarioTable(L);
return 0;
}
void ParseScenarioTable(lua_State* L) {
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (lua_istable(L, -1)) {
ParseScenarioTable(L);
std::cout << "Key: " << "key" << ", Value is table" << std::endl;
}
else if (lua_isstring(L, -1)) {
std::string x = lua_tostring(L, -1);
std::cout << "Key: " << "key" << ", Value: " << x << std::endl;
int i = 0;
}
else if (lua_isboolean(L, -1)) {
bool x = lua_toboolean(L, -1);
int i = 0;
std::cout << "Key: " << "key" << ", Value: " << x << std::endl;
}
lua_pop(L, 1);
}
}
Esta função lê apenas valores e funciona, quando executo no console obtenho:
Key: key, Value: 1
Key: key, Value: scenario1
Key: key, Value: scenario3
Key: key, Value: scenario2
Key: key, Value is table
Key: key, Value: test message
O problema é que não consigo ler também chaves de elementos de tabela aninhados. Eu mudei meu código com isso:
int ScenarioFunction(lua_State* L) {
int nargs = lua_gettop(L);
if (nargs != 1) {
return 0;
}
int type = lua_type(L, 1);
if (type != LUA_TTABLE) {
return 0;
}
ParseScenarioTable(L);
return 0;
}
void ParseScenarioTable(lua_State* L) {
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (lua_istable(L, -1)) {
std::string key = lua_tostring(L, -2);
ParseScenarioTable(L);
std::cout << "Key: " << key << ", Value is table" << std::endl;
}
else if (lua_isstring(L, -1)) {
std::string key = lua_tostring(L, -2);
std::string x = lua_tostring(L, -1);
std::cout << "Key: " << key << ", Value: " << x << std::endl;
int i = 0;
}
else if (lua_isboolean(L, -1)) {
std::string key = lua_tostring(L, -2);
bool x = lua_toboolean(L, -1);
int i = 0;
std::cout << "Key: " << key << ", Value: " << x << std::endl;
}
lua_pop(L, 1);
}
}
Mas se eu tentar ler as chaves, o programa irá quebrar e recebo um erro: Esta é a saída do meu programa:
Key: result, Value: 1
Key: 1, Value: scenario1
[2023-09-01 16:17:03.391093][error]: Error when running the script. Error is: invalid key to 'next'
onde invalid key to 'next'
está a string de erro de lua.
O que estou fazendo de errado? Como posso ler chaves e valores?
O problema está aqui:
O
lua_tostring
modifica seu argumento: ele substitui number1
por string"1"
no índice da pilha da API-2
, portanto, o seguintelua_next
não pode continuar percorrendo a tabela, pois recebe uma chave não existente"1"
em vez de existente1
.Este comportamento está descrito no manual .
Solução:
crie um slot de pilha temporário adicional para o valor a ser modificado por
lua_tostring
.Substituir
com