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/lua
的makefile
编译得到的
把源码放到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 额外的库。