c - Lua 在加载 dll 扩展时崩溃

标签 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 能够打印“一”和“二”,但在崩溃前无法打印“三”。这告诉我问题可能出在“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 而不是静态库以获得良好的形式。

As a bonus question: what should the return value of luaopen_mylib be?

在您的代码中,它实际上应该是 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

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

关于c - Lua 在加载 dll 扩展时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39398478/

相关文章:

c - 在 ubuntu 中使用数组与 popen 不起作用

windows - 为什么 GetCommandLineArgs 在运行 pwsh.exe 时返回一个 DLL?

python - Win 7中的greenlet : DLL failed: the specified procedure could not be found

c++ - 链接器和 dll 的 MSVC++ 2008 问题

c - 使用指针和引用函数

c - 阻止分配给数组的理由是什么?

python - 在 Windows 中使用 python 获取 ipconfig 结果

c++ - 将 UTF-8 字符转换为大写/小写 C++

c# 到非托管 c++ dll 访问冲突/"frame not in module"

validation - Windows DLL 是否由 Microsoft 签名?我可以检测它们是否被第三方篡改过吗?