I noticed that pushing and popping values onto/off the stack in lua
using the C
API on my target platform (32-bit
PowerPC
architecture) behaves very oddly. Consider the following test function:
void test_pushing_and_popping(lua_State *lua) {
printf("### STARTING PUSHING/POPPING TEST ###\n");
lua_dump_stack(lua);
const auto value = static_cast<uint32_t>(0x206D7578);
lua_pushinteger(lua, value);
lua_pushnumber(lua, value);
const auto popped_integer = lua_tointeger(lua, 1);
const auto popped_float = lua_tonumber(lua, 2);
printf("Popped integer: %llx\n", popped_integer);
printf("Popped float: %f\n", popped_float);
lua_dump_stack(lua);
printf("Asserting equality... ");
assert(popped_integer == popped_float);
printf("OK!\n");
printf("Wiping the stack...\n");
lua_settop(lua, 0);
lua_dump_stack(lua);
printf("### PUSHING/POPPING TEST ENDED ###\n");
}
I expect this code to run successfully and that the assertion will be passed since the same value is pushed and then popped with lua_pushinteger
, lua_pushnumber
, lua_tointeger
as well as lua_tonumber
respectively.
Indeed, if I run the code on Windows
as a 32-bit
binary, it works:
### STARTING PUSHING/POPPING TEST ###
Dumping the lua stack...
Stack element count: 0
Popped integer: 206d7578
Popped float: 544044408.000000
Dumping the lua stack...
Stack element count: 2
1 number 0x206D7578
2 number 0x206D7578
Asserting equality... OK!
Wiping the stack...
Dumping the lua stack...
Stack element count: 0
### PUSHING/POPPING TEST ENDED ###
Also on Linux
as 64-bit
binary it works.
However, here's the output on my target platform:
### STARTING PUSHING/POPPING TEST ###
Dumping the lua stack...
Stack element count: 0
Popped integer: 8002b2bc00e3a9ac <-- Wrong!
Popped float: 544044416.000000 <-- Wrong!
Dumping the lua stack...
Stack element count: 2
1 number 0x80000000 <-- Wrong!
2 number 0x206d7580 <-- Wrong!
Asserting equality... <-- Crash (assertion fail)!
What? The first value is completely wrong and even the 2nd value is wrong. 544044416.000000
converted to hexadecimal is 0x206d7580
which is also unequal to the pushed value of 0x206D7578
. Where does the inaccuracy come from?).
I'm pretty sure I didn't corrupt anything since I ran the test right after initializing lua
:
printf("Initializing lua...\n");
lua = luaL_newstate(); /* Opens Lua */
luaL_openlibs(lua); /* Opens the standard libraries */
test_pushing_and_popping(lua);
Does anyone have an idea what could be the problem?
The initial compliation error I got was worded as follows:
#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \
or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)"
It turns out I used the -DLUA_32BITS
compilation flag which causes the data type sizes to be too small:
#define LUA_INTEGER int
#define LUA_NUMBER float
Using the largest possible is the way to go which can be accomplished with the flag: -DLUA_C89_NUMBERS
.
This defines the data types as:
#define LUA_INTEGER long
#define LUA_NUMBER double