[√]lua加载dll

328 阅读2分钟

排查错误

error loading module 'xxx' from file 'xxxx.dll':

lua有自己的入口函数规则lua_open_模块名字,需要匹配,不能随便调整目录结构:

LUASOCKET_API int luaopen_socket_core(lua_State *L) {}

/* prefix for open functions in C libraries */
#define LUA_POF		"luaopen_"
#define POF		LUA_POF
static const char *mkfuncname (lua_State *L, const char *modname) {
  const char *funcname;
  const char *mark = strchr(modname, *LUA_IGMARK);
  if (mark) modname = mark + 1;
  funcname = luaL_gsub(L, modname, ".", LUA_OFSEP);
  funcname = lua_pushfstring(L, POF"%s", funcname);
  lua_remove(L, -2);  /* remove 'gsub' result */
  return funcname;
}

mkfuncname 是一个辅助函数,用于构建在 C 函数库中打开指定模块的函数名。它根据模块名生成 C 函数名,并将其格式化为 "luaopen_模块名" 的形式。在 Lua 调用 require 加载 C 函数库时,会调用这个生成的函数来进行初始化。这个函数使用 Lua 的字符串操作函数 luaL_gsub 将模块名中的 "." 替换为当前系统默认的函数名分隔符(通过 LUA_OFSEP 宏定义),然后调用 lua_pushfstring 将函数名压入 Lua 栈中。最后,通过 lua_remove 移除之前调用 luaL_gsub 生成的结果字符串。

一直报错找不到模块

image.png 原因是我的lua动态库名字不一致导致 image.png

可以看到core.dll依赖的是lua5.1.dll,如果随便将lua模块编译为lua.dll,可能就无法正确加载core.dll

要注意自己编译dll的时候,使用的lua版本,和宿主的lua版本必须一致,一般这种情况发生在分开编译dll和exe时比较容易发生。

lua dll demo

自己写的学习例子,一个最简单的lua dll:

#include <lua.h>					 
#include <lauxlib.h>					 
#include <stdio.h>
 
 
/**
 * 定义在lua中可调用的函数,要遵循规范:返回值必须为int,需传入lua_State
 */
static int test(lua_State *L);
 
int luaopen_dbg(lua_State *L);
#include "dbg.h"
static int test(lua_State *L)
{
    size_t len = 0;
    int num = luaL_checkinteger(L, 1);
    const char *str = luaL_checklstring(L, 2, &len);
    printf("come from test: num = %d	str = %s	len = %d\n", num, str, len);
    return 0;
}

int luaopen_dbg(lua_State *L)
{
    luaL_Reg l[] =
        {
            {"test", test},
            {NULL, NULL}};

    // luaL_newlib(L, l); // lua504才有这个函数
    luaL_register(L, "dbg", l);
    return 1;
}

定一个了一个dbg模块,在使用时将编译好的dbg.dll放在和lua.5.1.dll同目录,直接require,调用相关的函数即可

local lib = require(libName)
lib:test()

用法

dll的用法有点类似模块化开发,我们可以将不同的功能封装为一个模块,并编译为dll提供给别人使用,如果模块发生了更新,我只需要更新这个模块的dll就行了。

我还见过一种用法,你希望自己的应用软件仅仅是个壳,具体的实现放到了dll中,使用lua脚本调用dll,完成逻辑的执行,这种模式下的软件,其实dll非常有用,做WG的最喜欢这种方式。

在手游开发中,很少使用到这种技术,因为动态库有点水土不服。