注册c模块到lua中使用
#define REGISTER_CUSTOM_LIBRARY(name, lua_c_fn) \
int lua_c_fn(lua_State*); \
luaL_requiref(L, name, lua_c_fn, 0); \
lua_pop(L, 1) /* remove lib */
//注册c模块
void open_custom_libs(lua_State* L) {
//core
REGISTER_CUSTOM_LIBRARY("moon.core", luaopen_moon_core);
}
//c模块中的函数
int LUAMOD_API luaopen_moon_core(lua_State* L) { luaL_Reg l[] = { { "clock", lmoon_clock }, { "md5", lmoon_md5 }, { "tostring", lmoon_tostring }, { "timeout", lmoon_timeout }, { "log", lmoon_log }, { "loglevel", lmoon_loglevel }, { "cpu", lmoon_cpu }, { "send", lmoon_send }, { "new_service", lmoon_new_service }, { "kill", lmoon_kill }, { "scan_services", lmoon_scan_services }, { "queryservice", lmoon_queryservice }, { "next_sequence", lmoon_next_sequence }, { "env", lmoon_env }, { "server_stats", lmoon_server_stats }, { "exit", lmoon_exit }, { "now", lmoon_now }, { "adjtime", lmoon_adjtime }, { "callback", lua_service::set_callback }, { "decode", message_decode }, { "redirect", message_redirect }, { "collect", lmi_collect }, { "escape_print", escape_print }, { "signal", moon_signal }, /* placeholders */ { "id", NULL }, { "name", NULL }, { "timezone", NULL }, { NULL, NULL } }; luaL_newlib(L, l); const lua_service* S = lua_service::get(L); lua_pushinteger(L, S->id()); lua_setfield(L, -2, "id"); lua_pushlstring(L, S->name().data(), S->name().size()); lua_setfield(L, -2, "name"); lua_pushinteger(L, moon::time::timezone()); lua_setfield(L, -2, "timezone"); return 1; }
上边代码是moon框架中注册core模块的操作,可以看出主要是调用了luaL_requiref和lua_pop。luaL_requiref会在LOADED表中查找key为modname的值是否存在,不存在就调用lua_call执行传入的openf函数(luaopen_moon_core),最后调用lua_pop弹出栈上的LOADED表。

luaopen_moon_core又干了什么事情呢,查看源码可以发现调用了luaL_newlib创建一个表(根据luaL_Reg数组)key和value分别对应字符串和注册的函数。
有趣的是,moon还添加了额外的字段到表中,代码如下:

lua_pushinteger(L, S->id()); //栈顶压入int值
lua_setfield(L, -2, "id"); //在-2位置的表中(luaL_newlib创建在栈上的),向表中插入元素(key为“id”,value为栈顶元素t["id"]=value,然后弹出int值,需要注意这里弹出只是移动了栈指针,并不会清空元素,因为栈元素其实是一个union+类型枚举,所以可以复用栈元素(即使下次push的不是int值也无所谓,tt_和value_会设置对应的值)

结论:
注册moon.core模块完成后,LOADED表的内容格式如下:

在lua中使用模块:
-- 当用户执行 require "moon.core" 时 local moon = require "moon.core" -- 此时 moon 变量指向 package.loaded["moon.core"] 表 print(moon.id) -- 访问特殊字段 print(moon.name) print(moon.timezone) -- 调用函数 local t = moon.clock() -- 调用 lmoon_clock 函数 local hash = moon.md5("hello") -- 调用 lmoon_md5 函数

浙公网安备 33010602011771号