作为一种嵌入式语言,lua提供了一套完备的 C API来帮助 lua 与 宿主程序进行交互。因此使用 C 或者 C++ 来为lua编写模块是很容易的。
看一下lua (5.1) 中对 string 模块的封装源码 lstrlib.c
在 lstrlib.c 最后有这样的代码
/**
将函数名与实际调用函数记录在一个 struct 中,并组成一个数组
--- 有点 lua 代码的赶脚 ---
**/
static const luaL_Reg strlib[] = {
{"byte", str_byte},
{"char", str_char},
{"dump", str_dump},
{"find", str_find},
{"format", str_format},
{"gmatch", gmatch},
{"gsub", str_gsub},
{"len", str_len},
{"lower", str_lower},
{"match", str_match},
{"rep", str_rep},
{"reverse", str_reverse},
{"sub", str_sub},
{"upper", str_upper},
{"pack", str_pack},
{"packsize", str_packsize},
{"unpack", str_unpack},
{NULL, NULL}
};
/**
这里是对创建的lib 元表进行后续加工,具体可以看源代码
**/
static void createmetatable (lua_State *L) {
....
}
/*
** Open string library
** 这里是string 库的主入口
*/
LUAMOD_API int luaopen_string (lua_State *L) {
luaL_newlib(L, strlib); // 创建一个 lib 元表,并将 strlib 5.2之前使用luaL_register(L, "modulename", modulename); 中的函数名与函数放到表中
createmetatable(L); // 对创建的 lib 元表进行再次处理
return 1;
}
类似的代码也出现再了 loadlib.c(package模块)、loslib.c(os 模块)
因此可以总结出 lua 模块的编写方式
- 1、定义 C/C++ 中的 函数
- 2、定义 luaL_Reg 数组
- 3、创建 lib 元表。这里需要注意 在 5.2 之后的版本中可以直接使用 luaL_newlib,而之前的版本需要使用 luaL_register(L, "modulename", modulename);
C/C++ 与 lua 类型
将数据传入lua接口
/**
向栈中压入 NULL
**/
LUA_API void (lua_pushnil) (lua_State *L);
/**
向栈中压入 double
**/
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
/**
向栈
**/
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
/**
将字符串s的指定长度len压入栈中
**/
LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
/**
向栈中压入一个字符串
**/
LUA_API void (lua_pushstring) (lua_State *L, const char *s);
/**
向栈中压入字符串并格式化
**/
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
va_list argp);
/**
向栈中压入字符串并格式化
使用可变参数进行格式化
**/
LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
/**
向栈中压入一个C函数
**/
LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
/**
将 b 作为布尔值压入栈中
**/
LUA_API void (lua_pushboolean) (lua_State *L, int b);
/**
将一个轻量用户数据压入栈中
**/
LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
/**
"L"表示的线程入栈。如果这个线程是当前状态机的主线程的话,返回1。
**/
LUA_API int (lua_pushthread) (lua_State *L);