strange behavior of lua_getfield - c++

I have spotted strange behavior with lua_getfield() function. Please look at this code fragment, which should just get a field from table located at the stack top:
if(lua_istable(L,-1)){
lua_getfield(L,-1,"field_name");
int type = lua_type(L,-1); // returns LUA_TNIL
int field_value = lua_tointeger(L,-1); // returns 0
lua_pop(L,1);
// and now let's try iterating all table's fields:
lua_pushnil(L); // first key
while(lua_next(L, -2) != 0){
// uses 'key' (at index -2) and 'value' (at index -1)
CString key = lua_tostring(L,-2);
int type = lua_type(L,-1);
if(key == "field_name"){ //
int value = lua_tointeger(L,-1); // returns correct value!!!! (type == LUA_TNUMBER)
// ????? what the heck ????
}
// removes 'value'; keeps 'key' for next iteration
lua_pop(L, 1);
}
The question is, why lua_getfield() doesn't work, while lua_next() works perfectly?
I have used lua_getfield() tens of times with no problems and now I'm bumping my head into my keyboard...
reagards
Marcin

Problem solved. There was a problem with adjusting the number of results returned by previous call to lua_pcall. What confuses me though, is why lua_next worked correctly when lua_getfield() miserabely failed...

Related

Accessing a Lua table within a table from C++ side

I'm trying to transfer a table where there may be nested tables from the lua and write to a .ini file. But I just can not how I need to go on the stack to get data from nested tables. This code does not work as it should. Function setData work not correctly. What could be the problem?
C++ code
int sasl::LuaUtilities::luaWriteIni(LuaState inOutState)
{
string path;
boost::property_tree::ptree iniTree;
LUA_CHECK_NARG_EQ(inOutState, 2);
LUA_GET_PARAM(inOutState, 1, path);
int nargs = lua_gettop(inOutState);
for (int i = 1; i <= nargs; i++) {
if (lua_istable(inOutState, nargs)) {
setData(inOutState, nargs, iniTree);
}
}
return 0;
}
void sasl::LuaUtilities::setData(LuaState inOutState, int index, boost::property_tree::ptree & inIniTree)
{
// Push an initial nil to init lua_next
lua_pushnil(inOutState);
// Parse the table at index
while (lua_next(inOutState, index))
{
if (lua_istable(inOutState, index))
{
setData(inOutState, index, inIniTree);
}
else
{
string key = lua_tostring(inOutState, -2);
string value = lua_tostring(inOutState, -1);
}
// Pop value, keep key
lua_pop(inOutState, 1);
}
return;
}
Lua code
t = {}
local fileName = findResourceFile("test.ini")
t = readINI(fileName)
writeINI(fileName, t) --this not work in c++ side
There are two problems. lua_istable(inOutState, index) is wrong, because index is not the value of the key retrieved by next. That index is always the table you're iterating over. So you'll infinitely recurse over the same table when you call setData with that index.
In fact, passing index to setData itself is almost certainly wrong. Or at least, it's probably not right. You want to use relative indices here, but calling next pushes an extra value onto the stack.
What you probably want to do is have setData assume that the table to iterate over is at index -1 (ie: the top of the stack). That way, you're just calling lua_next(state, -2) (this is -2 because the key to get the next one for is at the top). And when you recursively call setData for a table value, you don't need to provide an index, because the table value is already at the top of the stack.
The second problem is that you never write the key/value pairs. You also never check to see if the value is something which can be converted to a string. It could be a Lua userdata.

How to pass a table parameter from lua to C++ through a lightuserdata object?

I have registered a function that creates a lightuserdata to be used by C++ and lua. that part is working fine when I tested using simple variables, ints and strings. I can create my lightuserdata in lua without errors when it's strings and ints. however when I try to use tables it gets more complicated
std::string aString = lua_tostring(lua,-4);
first parameter being correct as it is supposed to be a string
if (lua_type(lua,-3 == LUA_TTABLE)) //is true so i know it recognizes it as a table
{
auto t = lua_gettable(lua, -3);
size_t tableLen = lua_rawlen(lua, -3); // also gives me the correct size
lua_settop(lua, 1); //this discards the rest right? which i don't want.
//luaL_checktype(lua, 1, LUA_TTABLE); //using this crashes the application expecting
// table but getting string
lua_getfield(lua, 1, "a");
lua_getfield(lua, 1, "b");
lua_getfield(lua, 1, "c");
lua_getfield(lua, 1, "d");
lua_getfield(lua, 1, "e");
std::cout << lua_gettop(lua) << std::endl; //after using the getfields i get the new table size
//correctly (i assume, it turns 1 more value than expected, i think it's the table itself.
//int a = luaL_checkinteger(lua, -5); //these don't work as they expect numbers but get nil
//int b = luaL_checkinteger(lua, -4);
//int c = luaL_checkinteger(lua, -3);
//int d = luaL_checkinteger(lua, -2);
//int e = luaL_checkinteger(lua, -1);
std::cout << lua_tointeger(lua, -2) << std::endl; //returns always 0
}
Trying to ignore the table and get the rest of the stack gives me an violation error on 0x000000, though the 3rd value debugs correctly as what is supposed to be and the 4th is empty, even though it passes correctly if i don't use table.
is What I'm trying to do possible proceeding like this?
any comment to the right direction would be appreciated.
also, what should I use if I don't know the name of the key in the table?
if (lua_type(lua,-3 == LUA_TTABLE)) //is true so i know it recognizes it as a table
Big error here, or you didn't post the actual code.
You're not checking the type of the value under index -3, you're asking the type of the value under index false, since -3 == LUA_TTABLE is clearly false.
Whatever crash that happens after that "check" - is a result of this error. It will recognize as a table anything that is not nil.

How to check if previous return is the current one?

I have the following code:
EDIT
....int l=0
char* FantasiaGameUtils::GetCurrentTask(char *chat_arg)
{ // I know the code looks disgusting but please ignore that as I am only testing now
static char *szTemp1="";
for(int i=0; i<loop; i++)
{
if(task[i][0]!=0)
{
sif (l==0)
{strcpy(chat_arg, task[i]);
}
else
{strcpy(chat_arg, task[i+1]);
}
strcpy(task[i], "");
if (szTemp1!="")
{
MessageBox(0, szTemp1, "szTemp Value", 0);
MessageBox(0, chat_arg, "Initial Value", 0);
return chat_arg != szTemp1 ? chat_arg : NULL;
} else {
l++;
szTemp1 = chat_arg;
MessageBox(0, szTemp1, "szTemp1 Value", 0); // #execute
return chat_arg;
}
}
strcpy(chat_arg, "");
}
return false;
}
EDIT
What I am trying to do is make the return sequence check the previous returned value, and if its not the same as the current one, then return the current value chat_arg, if it is, return NULL.
The purpose of this function is to get the users prompt from the global_chat. An example of a prompt would be !create <game-type> <game-time> <max-players>
This prompt would be individually stored by each word enter (after each space) into the task[][] array, respectively.
From there, this function goes into play. It should copy the current task value (the current word) into the chat_arg variable.
The problem I am experiencing is, for some reason every in my main game loop. The value of chat_arg is kept through-out the game loop. I want to clear this value. I've come up with this method of which I will check if the current value in the function is the same as the previous one and if it is, return NULL (clearing the value), if it's not, then there is no reason to clear the previous value so return the current value.
Might anyone have a better or improved way I can perform this check? Or can anyone PLEASE tell me how I can get the previous returned value from memory and check it against the current value? Thank-you!
1) Add C++ tag to your post, because it is not a pure C code.
for(int i=0; i < loop; i++) // This line will not compile using C compilers.
2) Better return 0 in below line. false does not match to char* you expect.
return false; -> return 0;
My solutions for your problem:
1) Create global variable and your local chat_arg compare to it.
extern char* g_prev_chat_arg = 0;
...
char* FantasiaGameUtils::GetCurrentTask(char *chat_arg)
{
...
//return chat_arg != /*previous return value*/ ? chat_arg : NULL;
if (0 == strcmp(chat_arg, g_prev_chat_arg))
{
return 0;
}
else
{
g_prev_chat_arg = chat_arg;
return chat_arg;
}
...
}
2) Create local static variable within your function char* FantasiaGameUtils::GetCurrentTask(char *chat_arg)and use it like above,
3) Store somewhere in code last returned value from char* FantasiaGameUtils::GetCurrentTask(char *chat_arg) and then pass it each time when you are calling GetCurrentTask(...)
char* FantasiaGameUtils::GetCurrentTask(const char* prev_chat_arg, char* chat_arg)

Determining length for an array allocation

This is the snippet of code that I'm puzzled about. I'm checking for how long an incoming string is. I've appended * in order to have a sentinel value to stop the while loop. Yet, I'm consistently getting a length value that is inclusive of the * and I don't understand why, since the while loop with the nested if ought to stop prior to the *. Can someone point out what I'm doing wrong and why I'm having this issue?
void conversion(string romanIn)
{
length=0;
romanIn.append("*");
while(item!="*")
{
if(item != "*")
{
item = romanIn[length];
length++;
}
cout<<item;
}
you are naturally going to get a +1 the first time through the loop because you aren't initializing the variable "item". Also make it a do while instead of a while loop.
Try this:
do
{
// This line moves out of the if statement
item = romanIn[length];
if(item != "*")
{
length++;
}
cout<<item;
}while(item!="*")
What is the initial value of item?
Let's assume it's 0. You enter the loop
item == 0 != marker, so you enter the if as well, and you say
item = romanIn[0], length++
If romanIn[0] == "*" you will exit the loop, but your length now says 1 which includes the marker

Lua Accessing a table's Keys and Values

I would like to read a Lua file in a level editor so I can display its data in visual format for users to edit.
If I have a Lua table like so:
properties = {
Speed = 10,
TurnSpeed = 5
}
Speed is obviously the key and 10 the value. I know I can access the value if I know the key like so (provided the table is already on the stack):
lua_pushstring(L, "Speed");
lua_gettable(L, idx);
int Speed = lua_tointeger(L, -1);
lua_pop(L, 1);
What I want to do is access the key's name and the corresponding value, in C++. Can this be done? If so how do I go about it?
This is covered by the lua_next function, which iterates over the elements of a table:
// table is in the stack at index 't'
lua_pushnil(L); // first key
while (lua_next(L, t) != 0)
{
// uses 'key' (at index -2) and 'value' (at index -1)
printf("%s - %s\n", luaL_typename(L, -2), luaL_typename(L, -1));
// removes 'value'; keeps 'key' for next iteration
lua_pop(L, 1);
}
lua_next keys off of the, um, key of the table, so you need to keep that on the stack while you're iterating. Each call will jump to the next key/value pair. Once it returns 0, then you're done (and while the key was popped, the next wasn't pushed).
Obviously adding or removing elements to a table you're iterating over can cause issues.