cloudwu / skynet

A lightweight online game framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

skynet加载自定义c模块成功,table也能打印出两个函数名称,但是调用时函数为nil

xialeistudio opened this issue · comments

C代码

提供gbk和utf8互转函数。

#include <iconv.h>
#include <lauxlib.h>
#include <lua.h>
#include <stdlib.h>
#include <string.h>

// 全局变量,用于存储 iconv 句柄
static iconv_t cd_utf8_to_gbk = (iconv_t)-1;
static iconv_t cd_gbk_to_utf8 = (iconv_t)-1;

static int utf8togbk(lua_State *L) {
  const char *utf8str = luaL_checkstring(L, 1);
  if (cd_utf8_to_gbk == (iconv_t)-1) {
    cd_utf8_to_gbk = iconv_open("GBK", "UTF-8");
    if (cd_utf8_to_gbk == (iconv_t)-1) {
      lua_pushnil(L);
      lua_pushstring(L, "Failed to open iconv for UTF-8 to GBK conversion");
      return 2;
    }
  }

  size_t inlen = strlen(utf8str);
  size_t outlen = inlen * 2;  // Assume worst-case scenario

  char *gbkstr = (char *)malloc(outlen);
  memset(gbkstr, 0, outlen);

  char *inbuf = (char *)utf8str;
  char *outbuf = gbkstr;

  if (iconv(cd_utf8_to_gbk, &inbuf, &inlen, &outbuf, &outlen) == (size_t)-1) {
    free(gbkstr);
    lua_pushnil(L);
    lua_pushstring(L, "Failed to convert UTF-8 to GBK");
    return 2;
  }

  lua_pushstring(L, gbkstr);
  return 1;
}

static int gbktoutf8(lua_State *L) {
  const char *gbkstr = luaL_checkstring(L, 1);

  if (cd_gbk_to_utf8 == (iconv_t)-1) {
    cd_gbk_to_utf8 = iconv_open("UTF-8", "GBK");
    if (cd_gbk_to_utf8 == (iconv_t)-1) {
      lua_pushnil(L);
      lua_pushstring(L, "Failed to open iconv for GBK to UTF-8 conversion");
      return 2;
    }
  }

  size_t inlen = strlen(gbkstr);
  size_t outlen = inlen * 3;  // Assume worst-case scenario

  char *utf8str = (char *)malloc(outlen);
  memset(utf8str, 0, outlen);

  char *inbuf = (char *)gbkstr;
  char *outbuf = utf8str;

  if (iconv(cd_gbk_to_utf8, &inbuf, &inlen, &outbuf, &outlen) == (size_t)-1) {
    free(utf8str);
    lua_pushnil(L);
    lua_pushstring(L, "Failed to convert GBK to UTF-8");
    return 2;
  }

  lua_pushstring(L, utf8str);
  return 1;
}

LUAMOD_API int luaopen_iconv(lua_State *L) {
  luaL_Reg iconvlib[] = {
      {"utf8togbk", utf8togbk},
      {"gbktoutf8", gbktoutf8},
      {NULL, NULL},
  };
  luaL_checkversion(L);
  luaL_newlib(L, iconvlib);
  return 1;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.20)
project(demo C)

set(CMAKE_C_STANDARD 11)
set(CMAKE_OSX_ARCHITECTURES "arm64")
set(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
#lua & skynet
include_directories(./skynet/3rd/lua)
link_directories(./skynet/3rd/lua)
include_directories(./skynet/skynet-src)
# iconv
include_directories(/opt/homebrew/Cellar/libiconv/1.17/include)
link_directories(/opt/homebrew/Cellar/libiconv/1.17/lib)
# jemalloc
add_compile_definitions(NOUSE_JEMALLOC)
# luaiconv
add_library(luaiconv SHARED luaclib-src/iconv.c)
target_link_libraries(luaiconv iconv lua)

lua代码

local iconv = require("iconv")
for k, v in pairs(iconv) do
    print(k .. "!" .. type(v))
end
print(iconv.utf8togbk)

标准输出

[:00000002] LAUNCH snlua bootstrap
[:00000003] LAUNCH snlua launcher
[:00000004] LAUNCH snlua cdummy
[:00000005] LAUNCH harbor 0 4
[:00000006] LAUNCH snlua datacenterd
[:00000007] LAUNCH snlua service_mgr
[:00000008] LAUNCH snlua main
utf8togbk!function
gbktoutf8!function
nil

问题

从标准输出可以看到两个函数,但是打印iconv.utf8togbk得到nil,不清楚是不是skynet自带lua的问题。辛苦云大看看

如果你怀疑和 skynet 修改 lua vm 有关,可以换成官方版本试试。skynet 并不依赖这些修改。

gbktoutf8!function
utf8togbk!function
function: 0x7f737d2c3250

我用makefile编译出来没有问题

$(LUA_CLIB_PATH)/iconv.so : lualib-src/lua-iconv.c | $(LUA_CLIB_PATH)
	$(CC) $(CFLAGS) $(SHARED) $^ -o $@

可能 target_link_libraries 里引用的 lua 跟 skynet的不是同一个 lua ,你翻翻之前的 issues ,应该有类似的。

skynet 的 lua vm 符号编译在主程序中,应该是不需要额外 link 的。

可能 target_link_libraries 里引用的 lua 跟 skynet的不是同一个 lua ,你翻翻之前的 issues ,应该有类似的。

感谢几位大佬迅速回复,link的lua库是skynet/3rd/luamakefile编译得到的

把源码放到skynet/lualib-src再修改skynet/Makefile增加一个编译目标后解决了,有点奇怪,这样的话相当于搞了个built-in模块了

[:00000002] LAUNCH snlua bootstrap
[:00000003] LAUNCH snlua launcher
[:00000004] LAUNCH snlua cdummy
[:00000005] LAUNCH harbor 0 4
[:00000006] LAUNCH snlua datacenterd
[:00000007] LAUNCH snlua service_mgr
[:00000008] LAUNCH snlua main
utf8togbk
gbktoutf8
function: 0x1005afb78

因为你额外 link 了 lua ,这并不需要。lua api 的所有符号都在执行文件里,并不需要 link 额外的库。