如何创建 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的主要内容,如果未能解决你的问题,请参考以下文章

Lua:未启用动态库。我该如何启用它们?

如何在 Alpine linux 上为 nginx 添加 Lua 模块?

请问自己的软件如何运行Lua脚本

lua如何混淆加密?

如何在 Windows 上集成 LuaJIT 和 LuaRocks?

为 Python 或 SWIG 模块创建编译 C-dll,如何继续?