我正在尝试在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的返回值应该是什么?
谢谢!
答案 0 :(得分:2)
我编译了你的代码,它工作正常。所以你的问题不是来自你的代码。我的猜测是你正在使用不同版本的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库,因为当你的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
我更喜欢这种方式,因为调用者可以决定将导入命名为什么,并且它不会污染全局空间。