零、前言
在之前 “Lua 模块与包” 的文章中,介绍了 Lua 通过 require
是如何引入一个模块的,其中 C 模块并未展开分享。今天就分享如何构建和使用一个 C 模块作为 Lua 的引入模块。
Lua 通过注册 C/C++ 函数,进行感知 C/C++ 函数。一旦 C/C++ 函数用 Lua 表示和存储,Lua 就会通过对其地址的直接引用来调用,Lua 对这些 C/C++ 函数的调用不再依赖于函数名、包的位置以及可见性规则。
一、为什么要使用 C 模块
当我们使用 C/C++ 函数来扩展 Lua 程序时,将其设计为一个 C 模块是一个很不错的考虑。
他可以方便后续代码的扩展,可能一开始只是需要几个函数,但后续需求上的扩展不会让代码混乱。而且逻辑是收拢在一起的,不会分散在多个地方,方便后续查阅和维护。
二、如何编写一个 C 模块
第一步,编写需要暴露给 Lua 的 C/C++ 函数。
这里举的例子是遍历一个给定路径下的文件,会返回一个 table ,table 中存放着该路径下的文件名。
具体细节就不再赘述,可以查阅上一篇 “Lua 调用 C++ 函数”
int l_dir(lua_State *L) {
// 检测入参是否为字符串
// 如果不是,则会抛出异常到 Lua 中,can't run config. file: .../6、Lua回调C++/调用C++函数/读取目录函数.lua:11: bad argument #1 to 'dir' (string expected, got table)
const char *path = luaL_checkstring(L, 1);
// 打开相应目录
DIR *dir = opendir(path);
if (dir == nullptr) {
// 抛异常至 Lua
luaL_error(L, strerror(errno));
}
// 创建表,用于装载目录下 "索引" 和 "文件名"
// 格式为 table[index] = "文件名"
lua_newtable(L);
int i = 1;
struct dirent *entry;
while ((entry = readdir(dir)) != nullptr) {
// 压入 key ,即索引
lua_pushinteger(L, i++);
// 压入 value ,即文件名
lua_pushstring(L, entry->d