当加载dll扩展时,Lua会崩溃



我试图在Windows上创建一个Lua dll扩展。我使用的是Lua 5.3。我的编译器来自MinGW,是gcc 4.9.3。

我的dll扩展的C代码是这样的:

#include <stdio.h>
#include <lua.h>
static int dub(lua_State *L) {
    const double a = lua_tonumber(L, 1);
    lua_pushnumber(L, a*2);
    return 1;
}
__declspec(dllexport) int __cdecl luaopen_mylib(lua_State *L){
    printf("Onen");
    lua_pushcfunction(L, dub);
    printf("Twon");
    lua_setglobal(L, "dub");
    printf("Threen");
    return 1;
}

我正在像这样编译我的dll:

gcc mylib.c -shared -o mylib.dll -llua

我的想法是,我可以从Lua加载它,并像这样使用它:

require "mylib"
print (dub(5)) --should print 10

然而,当我实际尝试运行Lua代码时,它在require "mylib"行崩溃了。DLL能够打印"1"one_answers"2",但在它崩溃之前不能打印"3"。这告诉我问题可能与'lua_setglobal'调用有关。

怎么了?如何进一步调试或修复它?

作为附加问题:luaopen_mylib的返回值应该是什么?

谢谢!

我编译了你的代码,它工作良好。所以你的问题不是来自你的代码。我猜你使用的是不同版本的Lua,或者链接出了问题。

有三个地方可能出现版本不匹配。

  1. 在你的#include <lua.h>
  2. 在您的构建行与-llua
  3. 当你运行lua可执行文件时

至关重要的是,这三个都是相同的lua版本。如果其中一个不匹配,就会导致你现在遇到的问题。我猜你的lua可执行版本与其他版本不匹配。

另一件要尝试的事情是,你的dll应该链接到lua dll。系统上应该有一个名为lua53.dll的文件。将其复制到构建目录。当您使用gcc编译时,请尝试这样做:

gcc mylib.c -shared -o mylib.dll lua53.dll

这意味着你的dll扩展调用与lua可执行文件使用的完全相同的lua代码。他们的方式,你现在有它,与-llua行,它似乎是你在lua静态链接。这几乎不是你想要的一个dll库,因为lua可执行文件将调用lua53.dll中的代码,而你的dll调用静态库中的单独代码。我不认为这是导致你撞车的唯一原因,但这不是好的练习。如果lua使用全局状态(它没有),这个链接问题肯定会导致崩溃。同样,如果你对lua53.dll进行编译,你会发现mylib.dll要小得多。

总之,我认为你有一个lua版本不匹配的地方,导致你的崩溃。您还应该链接到lua dll,而不是静态库,以获得良好的格式。

作为附加问题:luaopen_mylib的返回值应该是什么?

在你的代码中,它实际上应该是0而不是1。返回值是您希望require()调用返回的堆栈上剩余的内容的数量。您的库只是将自己推入全局状态,而不返回任何lua值。另一种方法是返回一个包含库函数的表。这样就不会污染全局状态。因为你的库只有一个函数,你可以像这样直接返回它:

__declspec(dllexport) int __cdecl luaopen_mylib(lua_State *L){
    lua_pushcfunction(L, dub);
    return 1;
}

然后在lua中使用:

local dub = require("mylib")
print (dub(5)) --should print 10

我更喜欢这种方式,因为调用者可以决定如何命名导入,而且它不会污染全局空间。

最新更新