Lua在加载dll扩展时会遇到困难

时间:2016-09-08 19:08:11

标签: c windows 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("One\n");
    lua_pushcfunction(L, dub);
    printf("Two\n");
    lua_setglobal(L, "dub");
    printf("Three\n");
    return 1;
}

我正在编译我的dll:

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

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

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

但是,当我实际尝试运行Lua代码时,它会在require "mylib"行崩溃。 DLL能够打印“One”和“Two”,但它在崩溃之前无法打印“Three”。这告诉我问题可能是'lua_setglobal'调用。

出了什么问题?如何进一步调试或修复它?

作为一个额外的问题:luaopen_mylib的返回值应该是什么?

谢谢!

1 个答案:

答案 0 :(得分:2)

我编译了你的代码,它工作正常。所以你的问题不是来自你的代码。我的猜测是你正在使用不同版本的Lua,否则链接就会出错。

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

  1. #include <lua.h>
  2. 在使用-llua
  3. 的构建行中
  4. 运行lua可执行文件
  5. 至关重要的是,所有这三个都是相同的lua版本。如果一个不匹配,那可能会导致您遇到的问题。我猜你的lua可执行版本与其他版本不匹配。

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

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

    这意味着您的dll扩展名调用与lua可执行文件使用完全相同的lua代码。他们现在拥有它,使用-llua行,您似乎静态链接lua。这几乎不是你想要的dll库,因为当你的dll在静态库中调用单独的代码时,lua可执行文件将调用lua53.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
    

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