Hi, all,
Current LuaJIT's light userdata will cause errors when its payload value is
larger than 47 bits (e.g. ARM64 platform). Here are 2 cases:
-. lua_cpcall Lua API
-. an example is attached in the file: foo.c
-. this issue is also mentioned at
https://github.com/LuaJIT/LuaJIT/issues/255
-. luaJIT_setmode Luajit API's LUAJIT_MODE_WRAPCFUNC
Here are my 2 proposals to work around this issue. Which one do you prefer?
Or do you have other suggestions?
1. wrap light userdata in userdata for everywhere light userdata is used.
pros: Lua application code needs not any update.
cons: many parts of Luajit needs to be patched. For example Lua API,
bytecode implementation, IR implementation etc. Please refer my draft patch
for details.
I've worked out a draft patch for this proposal with a lot "FIXME"s:
https://github.com/zhongweiy/LuaJIT/commit/a18262b71c0bd6164258d60e3cf5d0e8846da088
. And the modification (includes FIXME) may be incomplete. Please tell me
if you find any missing.
2. provide alternative Lua API work around this issue. (refer foo.c and
lua_cpcall2 for details)
pros: compared with proposal 1, this fix in Luajit is relatively easy.
cons: user application code also needs an update.
Here is one possible new API (lua_cpcall2) for lua_cpcall:
*https://github.com/zhongweiy/LuaJIT/commit/657b641d929608c04ec4efba0f176f91170733ac
<https://github.com/zhongweiy/LuaJIT/commit/657b641d929608c04ec4efba0f176f91170733ac>*
Workaround for luaJIT_setmode() is similar:
- Application use userdata to wrap light userdata and push to Lua.
- Application call luaJIT_setmode(L, idx, LUAJIT_MODE_WRAPCFUNC2).
- In Luajit, VM will get userdata specified by idx and then unwrap
it to get the user passed function pointer.
--
Best regards,
Zhongwei
#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
int callback(lua_State *L) {
int *p = (int *)lua_touserdata(L, -1);
*p = 119;
return 0; //Number of values on stack to 'return' to lua.
}
int callback2(lua_State *L) {
int **ud = (int **)lua_touserdata(L, -1);
**ud = 2;
return 0;
}
int main(int argc, char *argv[])
{
lua_State *L = luaL_newstate();
if (!L)
return 1;
luaL_openlibs(L);
int x = 3;
printf("before lua_cpcall: x (addr:%p) = %d\n", &x, x);
int status = lua_cpcall(L, callback, &x);
if (status != 0) {
fprintf(stderr, "luajit internal error (error no:%d): %s\n", status,
lua_tostring(L, -1));
lua_pop(L, 1);
} else {
printf("after lua_cpcall: x = %d\n", x);
}
lua_close(L);
return 0;
}