lua5.3 批量注册c函数

cocos2d-x使用的lua版本号为5.1,使用的是luaL_register()函数来进行批量注册。下面说一下在5.3版本怎样批量注册函数。先以luaL_openlibs()函数为例。

static const luaL_Reg loadedlibs[] = {
  {"_G", luaopen_base},
  {LUA_LOADLIBNAME, luaopen_package},//package
  {LUA_COLIBNAME, luaopen_coroutine},//coroutine
  {LUA_TABLIBNAME, luaopen_table},//table
  {LUA_IOLIBNAME, luaopen_io},//io
  {LUA_OSLIBNAME, luaopen_os},//os
  {LUA_STRLIBNAME, luaopen_string},//string
  {LUA_MATHLIBNAME, luaopen_math},//math
  {LUA_UTF8LIBNAME, luaopen_utf8},//utf8
  {LUA_DBLIBNAME, luaopen_debug},//debug
#if defined(LUA_COMPAT_BITLIB)
  {LUA_BITLIBNAME, luaopen_bit32},
#endif
  {NULL, NULL}
};


LUALIB_API void luaL_openlibs (lua_State *L) {
  const luaL_Reg *lib;
  /* "require" functions from 'loadedlibs' and set results to global table */
  for (lib = loadedlibs; lib->func; lib++) {
    luaL_requiref(L, lib->name, lib->func, 1);
    lua_pop(L, 1);  /* remove lib */
  }
}

luaL_openlibs()会遍历loadedlibs数组,并调用luaL_requiref函数,对于这个函数,官网上这么解释:

void luaL_requiref (lua_State *L, const char *modname,
                    lua_CFunction openf, int glb);

If modname is not already present in package.loaded, calls function openf with string modname as an argument and sets the call result in package.loaded[modname], as if that function has been called through require.

If glb is true, also stores the module into global modname.

Leaves a copy of the module on the stack.

如果在package.loaded中不存在nodname这个字段,就调用openf这个函数,并且把返回值命名为modname,同时赋值给package.loaded[modname](相当于 require)。如果glb为true的话,会存储这个模块为_G[modname]。并且会留下拷贝到栈中。

因此luaL_openlibs()的功能就是:遍历数组,加载对应的模块并赋值,之后清除栈中的副本。

接下来以math模块为例:

static const luaL_Reg mathlib[] = {
  {"abs",   math_abs},
  {"acos",  math_acos},
  {"asin",  math_asin},
  {"atan",  math_atan},
  {"ceil",  math_ceil},
  {"cos",   math_cos},
  {"deg",   math_deg},
  {"exp",   math_exp},
  {"tointeger", math_toint},
  {"floor", math_floor},
  {"fmod",   math_fmod},
  {"ult",   math_ult},
  {"log",   math_log},
  {"max",   math_max},
  {"min",   math_min},
  {"modf",   math_modf},
  {"rad",   math_rad},
  {"random",     math_random},
  {"randomseed", math_randomseed},
  {"sin",   math_sin},
  {"sqrt",  math_sqrt},
  {"tan",   math_tan},
  {"type", math_type},
#if defined(LUA_COMPAT_MATHLIB)
  {"atan2", math_atan},
  {"cosh",   math_cosh},
  {"sinh",   math_sinh},
  {"tanh",   math_tanh},
  {"pow",   math_pow},
  {"frexp", math_frexp},
  {"ldexp", math_ldexp},
  {"log10", math_log10},
#endif
  /* placeholders */
  {"pi", NULL},
  {"huge", NULL},
  {"maxinteger", NULL},
  {"mininteger", NULL},
  {NULL, NULL}
};


/*
** Open math library
*/
LUAMOD_API int luaopen_math (lua_State *L) {
  luaL_newlib(L, mathlib);
  lua_pushnumber(L, PI);
  lua_setfield(L, -2, "pi");
  lua_pushnumber(L, (lua_Number)HUGE_VAL);
  lua_setfield(L, -2, "huge");
  lua_pushinteger(L, LUA_MAXINTEGER);
  lua_setfield(L, -2, "maxinteger");
  lua_pushinteger(L, LUA_MININTEGER);
  lua_setfield(L, -2, "mininteger");
  return 1;
}
在luaopen_math函数中,先创建了一个注册了mathlib数组函数的table,并放入栈顶。之后在这个table中添加了"pi" "huge" "maxinteger" "mininteger"字段,此时在栈中存在的就是luaL_newlib创建的table。然后在lua_openlibs()中给这个table命名为math。在mathlib数组的后面添加了几个等字段如huge的原因只是起到一个占位符的作用,即证明在math包里存在这个字段,删去亦可。
综上,如果我们要批量注册的话,我们可以先调用luaL_newlib函数创建一个table,之后调用luaL_requiref函数为这个table赋值并放入_G以及赋值给package.loaded中,然后再调用lua_pop(1)清除副本即可。

猜你喜欢

转载自blog.csdn.net/bull521/article/details/79938211