Win x64下Lua调用DLL返回函数而非数值且Lua53崩溃求助
Lua调用DLL函数返回函数而非预期数值,Lua5.3运行崩溃问题
环境与现象
- 运行环境:Win x64 系统,使用
lua53.exe或lua54.exe - 操作逻辑:通过
package.loadlib加载jsyslog.dll中的test函数,预期调用test()返回数值3 - 实际结果:
- 输出两次
Test result function: 00000000704186d0 lua53.exe执行后直接崩溃lua54.exe无崩溃,但返回的是函数对象而非预期的数值3
- 输出两次
问题根源
package.loadlib的调用要求:该函数加载DLL导出函数后,返回的可调用对象要求导出函数必须严格遵循Lua C API规范——即函数签名为int lua_CFunction(lua_State *L),通过操作Lua栈传递参数和返回值,返回值为栈上结果的数量。- DLL函数不符合规范:若
jsyslog.dll中的test是普通C函数(比如直接返回int的int test()),而非适配Lua的C函数,调用时会破坏Lua栈结构,导致Lua5.3崩溃;Lua5.4虽有栈保护,但无法将普通函数的返回值转为Lua数值,因此返回的仍然是加载后的函数对象。
解决方案
方案1:修改DLL代码,遵循Lua C API规范
重新编译 jsyslog.dll,让 test 函数适配Lua的C函数要求:
#include <lua.h> #include <lauxlib.h> // 符合Lua C API的test函数 static int test(lua_State *L) { lua_pushinteger(L, 3); // 将数值3压入Lua栈 return 1; // 返回栈上结果的数量(此处为1个) } // 定义库函数表 static const luaL_Reg jsyslog_lib[] = { {"test", test}, {NULL, NULL} // 表结束标记 }; // 库的入口函数,供Lua加载 int luaopen_jsyslog(lua_State *L) { luaL_newlib(L, jsyslog_lib); return 1; }
编译后,可通过以下Lua代码调用:
-- 方式1:用require加载库 local jsyslog = require("jsyslog") local result = jsyslog.test() print("Test result", result) -- 方式2:用package.loadlib加载入口函数 local load_lib, err = package.loadlib("jsyslog.dll", "luaopen_jsyslog") if not load_lib then error(err) end local jsyslog = load_lib() local result = jsyslog.test() print("Test result", result)
方案2:使用FFI调用普通C函数(无需修改DLL)
如果无法修改DLL,可借助Lua的FFI库(LuaJIT内置,Lua5.4可使用第三方luaffi库)直接调用普通C函数:
local ffi = require("ffi") -- 声明函数原型 ffi.cdef[[ int test(); ]] -- 加载DLL并调用函数 local jsyslog = ffi.load("jsyslog.dll") local result = jsyslog.test() print("Test result", result)
内容的提问来源于stack exchange,提问作者josh assing
相关产品推荐
相关产品推荐

