所以我在Visual Studio 2017中用C ++编写了一个小的.dll。 它只是导出一个我从lua脚本调用的函数。 lua脚本在第三方应用程序中运行;我想用这个库扩展它的功能。 我必须使用 package.loadlib ,因为修改了 require 并且只允许加载.lua文件。 (我确认它确实找到.dll文件,所以它与包路径无关)
#include "lua.hpp"
extern "C" __declspec(dllexport) int test(lua_State* L) {
// luaL_checknumber(L, 1); // access violation
// lua_pushnumber(L, 123); // freeze
return 1;
}
我使用以下代码加载此函数:
test, err = package.loadlib(dllpath, "test")
print("test = ", test, "err = ", err)
print("test() = ", test())
print("done")
打印
test = function:001D168B err = nil
test()=功能:001D168B
完成
正如所料......
但是当我让库调用lua函数时,应用程序会永久冻结或获取访问冲突。 lua_push *函数会导致这些冻结,而luaL_check *函数会导致访问冲突。
我使用Windows 10(x64),应用程序为32位,我的.dll编译为32位,两者都具有完全相同的lua版本。
我做错了什么?
修改
我的确错了。当它应该是lua5.3-static.lib时,我链接了lua5.3.lib。我不知道。它现在正在运作。
答案 0 :(得分:0)
拥有完全相同的Lua版本是不够的。应用程序(尤其是游戏)修改Lua解释器非常常见。但是即使你有相同的源代码,在同一个程序中一起工作的编译的Lua C代码的两个副本(游戏中的一个,你的DLL中的一个)也不会起作用。这是因为C代码使用全局变量,并且因为有两个副本它们不同步而且会导致问题。
因此,如果你想调用lua_pushstring,你需要在游戏中找到该函数的地址。如果游戏是在DLL中使用Lua构建的,请找到该DLL,并使用Dependency Walker检查符号是否正确导出。否则请查看Dependency Walker中的游戏EXE,因为EXE也可以导出符号。一旦找到导出Lua C API的模块(DLL或EXE),就可以从该模块生成.lib,然后在自己的DLL中链接到它(不应包含Lua代码本身)