标准库加载
Lua 的核心解释器本身只提供虚拟机、垃圾回收和 C API。所有内置函数(print、math.sin、string.format
等)都来自标准库,由独立的 C 模块实现。
lualib.h
头文件 lualib.h 声明了所有标准库的打开函数:
| 函数 | 提供的 Lua 模块/全局 |
|---|---|
luaopen_base(L) | _G、assert、print、type、pairs 等基础函数 |
luaopen_coroutine(L) | coroutine |
luaopen_table(L) | table |
luaopen_io(L) | io |
luaopen_os(L) | os |
luaopen_string(L) | string |
luaopen_utf8(L) | utf8 |
luaopen_math(L) | math |
luaopen_debug(L) | debug |
luaopen_package(L) | package、require |
打开全部标准库
#include <lualib.h>
luaL_openlibs(L); // 打开所有标准库
这等价于依次调用上述所有 luaopen_* 函数。
按需加载
在沙箱或内存受限环境中,通常只加载必要的库:
luaopen_base(L);
luaopen_math(L);
luaopen_string(L);
// 不加载 io/os/debug,限制文件系统和环境访问
自定义 package 搜索器
luaopen_package 注册了 require 机制和默认搜索路径。你可以:
- 修改
package.path/package.cpath指向自定义目录 - 插入自定义搜索器到
package.searchers中 - 完全替换
require的实现(手动注册同名全局函数)
预加载模块
lauxlib.h 中定义了 Registry key:
#define LUA_PRELOAD_TABLE "_PRELOAD"
可以通过在预加载表中注册函数,让 require 在未找到文件时调用你的加载器:
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
lua_pushcfunction(L, my_custom_loader);
lua_setfield(L, -2, "mymodule");
lua_pop(L, 1);
之后在 Lua 中 require("mymodule") 就会调用 my_custom_loader。
完整代码
#include <assert.h>
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
#include <stdio.h>
static int open_mymodule(lua_State *L) {
lua_newtable(L);
lua_pushstring(L, "hello from preload");
lua_setfield(L, -2, "msg");
return 1;
}
int main(void) {
lua_State *L = luaL_newstate();
luaopen_base(L);
luaopen_math(L);
lua_setglobal(L, "math");
luaopen_string(L);
lua_setglobal(L, "string");
luaL_dostring(L, "print('math.pi =', math.pi)");
luaL_dostring(L, "print('string.upper =', string.upper('hi'))");
luaL_dostring(L, "print(io)");
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
lua_pushcfunction(L, open_mymodule);
lua_setfield(L, -2, "mymodule");
lua_pop(L, 1);
luaopen_package(L);
luaL_dostring(L, "local m = require('mymodule')\n"
"print('mymodule.msg =', m.msg)\n");
luaL_openlibs(L);
luaL_dostring(L, "print('os.time =', os.time())");
lua_close(L);
puts("19-stdlib: ok");
return 0;
}