joe 发表于 2022-6-20 15:54:54

Lua源码分析 - 扩展库篇 - 扩展库Open的实现(13)

目录

一、扩展库 - Open扩展库的配置

二、扩展库 - 扩展库Lib的配置详解

三、扩展库 - 基础库Base的配置详解

上一章,我们讲解了如何将Require进来。本章节具体将一下扩展库启动的实现。

一、扩展库 - Open扩展库的配置
启动一个扩展库,首先需要进行两个基础配置:loadedlibs数组配置 & 库名称和回调函数的定义(lualib.h)

loadedlibs是一个二维数组。第一个参数为库名称,第二个参数库open函数。
loadedlibs数组中,第一个对象为全局基础方法聚合(luaopen_base)。常见的loadfile函数等都在这上面配置,在lua语言中,直接使用函数即可,无需使用库名称.方法名称(例如:string.find)方式。
数组最后一个对象,为{NULL,NULL},主要用于在循环的时候遍历退出。
//---------------------linit.c
/*
** these libs are loaded by lua.c and are readily available to any Lua
** program
** LUA标准库常量
**
** 定义标准库名称 & 启动的方法
*/
static const luaL_Reg loadedlibs[] = {
{"_G", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package},
{LUA_COLIBNAME, luaopen_coroutine},
{LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io},
{LUA_OSLIBNAME, luaopen_os},
{LUA_STRLIBNAME, luaopen_string},
{LUA_MATHLIBNAME, luaopen_math},
{LUA_UTF8LIBNAME, luaopen_utf8},
{LUA_DBLIBNAME, luaopen_debug},
#if defined(LUA_COMPAT_BITLIB)
{LUA_BITLIBNAME, luaopen_bit32},
#endif
{NULL, NULL}
};
//......................lualib.h

LUAMOD_API int (luaopen_base) (lua_State *L);

#define LUA_COLIBNAME        "coroutine"
LUAMOD_API int (luaopen_coroutine) (lua_State *L);

#define LUA_TABLIBNAME        "table"
LUAMOD_API int (luaopen_table) (lua_State *L);

#define LUA_IOLIBNAME        "io"
LUAMOD_API int (luaopen_io) (lua_State *L);
二、扩展库 - 扩展库Lib的配置详解
我们以协程coroutine的扩展库作为例子来看。扩展库实现重点需要分三个部分:函数配置数组,扩展库加载方法,函数实现。

函数配置数组:主要定义了函数名称和对应的C语言函数。数组最后一个对象为{NULL,NULL},因为数组遍历的时候会根据NULL做判断进行弹出。
扩展库加载方法:入参为L,对当前的线程栈。方法内容必须实现luaL_newlib。该函数主要将配置数组中的方法,遍历注册到一个module=func数组上。该module数组,作为加载方法openf的结果放入栈上。
函数实现:每个函数的入参都为lua_State *L,为当前线程栈。
大家可能会有疑问,为何每个函数入参都会L,那在lua中调用的时候如何进行多个参数入参。实际上,lua语言还会解析语法本身,对于多个参数入参,也都会通过lua_push*方法,放入栈上,所以当调用函数的时候,往栈上取参即可。

//方法配置数组
static const luaL_Reg co_funcs[] = {
{"create", luaB_cocreate},
{"resume", luaB_coresume},
{"running", luaB_corunning},
{"status", luaB_costatus},
{"wrap", luaB_cowrap},
{"yield", luaB_yield},
{"isyieldable", luaB_yieldable},
{NULL, NULL}
};

//启动函数
LUAMOD_API int luaopen_coroutine (lua_State *L) {
luaL_newlib(L, co_funcs);
return 1;
}


/**
* 协程挂起函数
*
* L为当前协程函数的协程栈
* lua_gettop(L)获取当前操作函数到栈顶的栈个数
*/
static int luaB_yield (lua_State *L) {
return lua_yield(L, lua_gettop(L));
}
三、扩展库 - 基础库Base的配置详解
Lua的基础库就是定义了一些常用的函数,例如:print。这些函数作为全局函数,可以在Lua语言中直接调用。lbaselib.c。

base_funcs:基础库的数组配置。主要定义函数名称和对应的方法。

luaopen_base:基础库的启动函数。主要有三步:

从全局注册表中获取全局环境变量数组LUA_RIDX_GLOBALS,并通过luaL_setfuncs方法将基础库的函数逐个塞进全局环境变量上LUA_RIDX_GLOBALS=func
lua_pushvalue拷贝全局环境变量数组LUA_RIDX_GLOBALS,然后LUA_RIDX_GLOBALS=LUA_RIDX_GLOBALS,并将拷贝的数组pop弹出栈顶
lua_pushliteral栈顶设置一个字符串常量,用于存放版本信息,并设置LUA_RIDX_GLOBALS['_VERSION']=LUA_VERSION,然后将栈顶的版本信息pop弹出栈顶。
//基础库启动
LUAMOD_API int luaopen_base (lua_State *L) {
/* 打开全局环境变量数组LUA_RIDX_GLOBALS,放置到栈顶L->top open lib into global table */
lua_pushglobaltable(L);
/* 将base_funcs中的函数,逐个设置到LUA_RIDX_GLOBALS数组上 */
luaL_setfuncs(L, base_funcs, 0); //module 表
/* set global _G */
/* LUA_RIDX_GLOBALS = LUA_RIDX_GLOBALS*/
lua_pushvalue(L, -1);
lua_setfield(L, -2, "_G"); //弹出栈顶L->top--
/* /* LUA_RIDX_GLOBALS = LUA_VERSION set global _VERSION */
lua_pushliteral(L, LUA_VERSION);
lua_setfield(L, -2, "_VERSION"); //弹出栈顶L->top--
return 1;
}

//基础库配置
static const luaL_Reg base_funcs[] = {
{"assert", luaB_assert},
{"collectgarbage", luaB_collectgarbage},
{"dofile", luaB_dofile},
{"error", luaB_error},
{"getmetatable", luaB_getmetatable},
{"ipairs", luaB_ipairs},
{"loadfile", luaB_loadfile},
{"load", luaB_load},
#if defined(LUA_COMPAT_LOADSTRING)
{"loadstring", luaB_load},
#endif
{"next", luaB_next},
{"pairs", luaB_pairs},
{"pcall", luaB_pcall},
{"print", luaB_print},
{"rawequal", luaB_rawequal},
{"rawlen", luaB_rawlen},
{"rawget", luaB_rawget},
{"rawset", luaB_rawset},
{"select", luaB_select},
{"setmetatable", luaB_setmetatable},
{"tonumber", luaB_tonumber},
{"tostring", luaB_tostring},
{"type", luaB_type},
{"xpcall", luaB_xpcall},
/* placeholders */
{"_G", NULL},
{"_VERSION", NULL},
{NULL, NULL}
};

————————————————
版权声明:本文为CSDN博主「老码农zhuli」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/initphp/article/details/104374765

页: [1]
查看完整版本: Lua源码分析 - 扩展库篇 - 扩展库Open的实现(13)