Lua C 库访问违规和冻结

所以我用 C++ 和 Visual Studio 2017 写了一个小的 .dll。 它所做的只是导出一个函数,我从 lua 脚本中调用它。 这个 lua 脚本运行在一个第三方应用程序中,我想通过这个库扩展它的功能。 我必须使用 package.loadlib,因为 require 被修改了,只允许加载 .lua 文件。(我确认它确实可以找到 .dll 文件,所以它与包路径无关)

#include "lua.hpp"

extern "C" __declspec(dllexport) int test(lua_State* L) {
  // luaL_checknumber(L, 1); // 访问违规
  // lua_pushnumber(L, 123); // 冻结
  return 1;
}

我使用以下代码加载这个函数:

test, err = package.loadlib(dllpath, "test")

print("test = ", test, "err = ", err)
print("test() = ", test())
print("done")

打印出来的结果如下所示

test = function: 001D168B err = nil

test() = function: 001D168B

done

正如我所预期的那样...

但是当我调用库中的 lua 函数时,应用程序会永久地冻结或产生访问违规。 lua_push* 函数会导致这些冻结,而 luaL_check* 函数会导致访问违规。

我使用 Windows 10 (x64),应用程序是 32 位的,我的 .dll 编译成 32 位,它们都具有完全相同的 lua 版本。

我做错了什么?

编辑:

我的确链接错误了。我链接了 lua5.3.lib,而它应该是 lua5.3-static.lib。我不知道那个。现在它能正常工作了。

点赞
用户67432
用户67432

将 Lua 版本完全相同并不足够。应用程序(尤其是游戏)通常会修改 Lua 解释器。但即使您拥有相同的源代码,让两个已编译的 Lua C 代码副本(一个在游戏中,一个在 DLL 中)一起在同一程序中运行也是行不通的。这是因为 C 代码使用全局变量,因为有两个副本,它们不同步并且会导致问题。

因此,如果您想调用 lua_pushstring,您需要在游戏中查找该函数的地址。如果游戏是在 DLL 中构建的,请查找该 DLL,并使用 Dependency Walker 检查符号是否正确导出。否则,请查看 Dependency Walker 中的游戏 EXE,因为 EXE 也可以导出符号。一旦您找到导出 Lua C API 的模块(DLL 或 EXE),就可以从该模块生成 .lib,然后在您自己的 DLL 中链接它(该 DLL 不应包含 Lua 代码本身)。

2018-02-06 01:02:45