我正在尝试在 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,或者链接出了问题。
版本不匹配可能发生在三个地方。
- 在你的
#include <lua.h>
行 - 在您的构建行中使用
-llua
- 当您运行
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/