如何创建 Lua 模块的 dll
Posted
技术标签:
【中文标题】如何创建 Lua 模块的 dll【英文标题】:How to create dll of Lua Module 【发布时间】:2017-05-15 13:11:00 【问题描述】:我正在尝试编写一个外部 Lua 模块。
我在 Windows 8.1 上工作,我使用 gcc 作为编译器。
我的要求是自己构建/编译所有内容,而不使用在线提供的预编译文件。
首先,我构建Lua 5.2.4的C源代码如下:
gcc -c *.c
ren lua.o lua.obj
ren luac.o luac.obj
ar rcs luaX.X.X.lib *.o
gcc -shared -o luaX.X.X.dll *.o
gcc lua.c luaX.X.X.lib -o luaX.X.X.exe
gcc luac.c luaX.X.X.lib -o luacX.X.X.exe
del *.o *.obj
其中X.X.X
是源代码修订版。
创建 .exe 后,我会编写模块的 C 代码(我们称之为 LuaMath):
#include<windows.h>
#include<math.h>
#include "lauxlib.h"
#include "lua.h"
static int IdentityMatrix(lua_State *L)
int in = lua_gettop(L);
if (in!=1)
lua_pushstring(L,"Maximum 1 argument");
lua_error(L);
lua_Number n = lua_tonumber(L,1);
lua_newtable(L); /* tabOUT n */
int i,j;
for (i=1;i<=n;i++)
lua_newtable(L); /* row(i) tabOUT n */
lua_pushnumber(L,i); /* i row(i) tabOUT n */
for (j=1;j<=n;j++)
lua_pushnumber(L,j); /* j i row(i) tabOUT n */
if (j==i)
lua_pushnumber(L,1);
else /* 0/1 j i row(i) tabOUT n */
lua_pushnumber(L,0);
/* Put 0/1 inside row(i) at j position */
lua_settable(L,-4); /* i row(i) tabOUT n */
lua_insert(L,-2); /* row(i) i tabOUT n */
/* Insert row(i) into position in tabOUT */
lua_settable(L,2); /* tabOUT n */
return 1;
static const struct luaL_Reg LuaMath [] = "IdentityMatrix", IdentityMatrix,
NULL, NULL;
int __declspec(dllexport) luaopen_LuaMath(lua_State *L)
luaL_newlib(L,LuaMath);
return 1;
然后我编译它链接到动态 library.dll 如下:
gcc -shared -L "<path where luaX.X.X.dll is>" -l "luaX.X.X" LuaMath.c
当我将模块调用为 Lua 代码如下:
require("LuaMath")
输出是:
> require("LuaMath")
multiple Lua VMs detected
stack traceback:
[C]: in ?
[C]: in function 'require'
stdin:1: in main chunk
[C]: in ?
>
我做错了什么?
非常感谢。
【问题讨论】:
已编辑,因为我删除了最初的问题,但现在又出现了另一个问题。 Lua好像找不到我写的Module。 这有毒!请不要对问题做出如此重大的改变;它使以前未回答的答案无效,使为回答问题所付出的努力对未来的访问者无效,并可能对他们投反对票。 如果您有其他问题要问,请将其作为不同的问题! 我可以更改问题标题吗? 可以,只要您缩小问题范围即可。既然你已经把你的大部分代表作为赏金,一定要继续,只要它能解决你的问题。 【参考方案1】:不要将 Lua 库与您的 DLL 链接。这就是错误消息告诉您的内容。
【讨论】:
你的意思是“gcc -shared LuaMath.c”。如果是这样,它告诉我所有 Lua C API 函数都没有定义。 自述文件指出:此外,要为 Lua 动态加载 C 库,您需要知道如何创建动态库,并且您需要确保 Lua API 函数可供那些动态库——但不要将 Lua 库链接到每个动态库中。对于 Unix,我们建议将 Lua 库静态链接到宿主程序中,并将其符号导出以进行动态链接; src/Makefile 为 Lua 解释器执行此操作。对于 Windows,我们建议 Lua 库是 DLL。在所有情况下,编译器 luac 都应该是静态链接的。 没错。它说“......不要将Lua库链接到每个动态库......”,这是你在(两个)问题中做错的事情。 "... 我们建议将 Lua 库静态链接到宿主程序..." 而不要"... 链接到每个动态库..."。你明白吗?将 Lua 库 静态 链接到 宿主程序(即加载您尝试构建的 DLL 的同一程序)。我就是这么解释的…… 我解决了多VM问题,但是现在Lua找不到我写的模块 加载共享对象的路径由CPATH 或package.cpath 控制因此,请考虑将共享对象放在与您的Lua 脚本相同的目录中,或者.... 相应地修改package.cpath
变量。 【参考方案2】:
可能你需要定义一个 SYSCFLAGS LUA_BUILD_AS_DLL
然后再次编译 lua 代码
gcc -DLUA_BUILD_AS_DLL -c *.c
为什么不使用 Lua 源提供的 Makefile 呢?编译很简单,如果你阅读 Makefile,它会为你设置 gcc 标志。
cd /path/to/lua-src
make mingw
现在你应该在 /path/to/lua-src/src/ 中获得 lua.exe、luac.exe、lua53.dll
编译你的模块
gcc -shared -I/path/to/lua-src/src LuaMath.c -o LuaMath.dll -L/path/to/lua-src/src -llua53
【讨论】:
使用 -llua53 链接会产生重复的虚拟机。以上是关于如何创建 Lua 模块的 dll的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Alpine linux 上为 nginx 添加 Lua 模块?