基础 API 函数
1. lua_len(L, index)
- 作用:获取指定索引处值的长度(类似
#
操作符),结果压入栈顶。 - 参数:
L
(Lua 状态机),index
(目标值的栈位置)。 - 代码示例:
lua_pushstring(L, "Hello"); // 压入字符串 lua_len(L, -1); // 计算长度(结果为5) printf("Length: %lld\n", lua_tointeger(L, -1)); // 输出5 lua_pop(L, 2); // 清理栈(字符串和长度)
2. lua_load(L, reader, data, chunkname, mode)
- 作用:加载 Lua 代码块但不执行,需配合
lua_pcall
。 - 参数:
reader
(读取函数),data
(用户数据),chunkname
(调试名),mode
(加载模式)。 - 代码示例:
const char *code = "return 42"; lua_Reader reader = [](lua_State *L, void *data, size_t *size) { static int read = 0; if (!read) { *size = strlen((const char*)data); read = 1; return data; } return (const char*)NULL; }; if (lua_load(L, reader, (void*)code, "chunk", "t") == LUA_OK) { lua_pcall(L, 0, 1, 0); // 执行代码,返回42 printf("Result: %d\n", (int)lua_tointeger(L, -1)); }
3. lua_newstate(allocator, ud)
- 作用:创建独立 Lua 虚拟机,允许自定义内存分配。
- 参数:
allocator
(内存分配函数),ud
(用户数据)。 - 代码示例:
void* custom_alloc(void *ud, void *ptr, size_t osize, size_t nsize) { if (nsize == 0) { free(ptr); return NULL; } return realloc(ptr, nsize); } lua_State *L = lua_newstate(custom_alloc, NULL); // 创建新状态 lua_close(L); // 关闭
4. lua_newtable(L)
- 作用:创建空表并压入栈顶。
- 代码示例:
lua_newtable(L); // 创建新表 lua_pushstring(L, "value"); // 键为 "key" lua_pushinteger(L, 100); // 值 100 lua_settable(L, -3); // 表[-3] 设置键值对 lua_setglobal(L, "my_table"); // 设为全局变量
5. lua_newthread(L)
- 作用:创建新协程,返回其
lua_State
。 - 代码示例:
lua_State *co = lua_newthread(L); // 创建协程 lua_pushstring(co, "coroutine"); // 协程独立栈 lua_resume(co, L, 0); // 启动协程(需提前加载函数)
6. lua_newuserdata(L, size)
- 作用:分配用户数据内存并压入栈顶。
- 代码示例:
typedef struct { int x; } MyData; MyData *data = (MyData*)lua_newuserdata(L, sizeof(MyData)); data->x = 10; // 初始化 // 绑定元表 luaL_getmetatable(L, "MyData"); lua_setmetatable(L, -2);
7. lua_next(L, index)
- 作用:遍历表的键值对。
- 代码示例:
lua_getglobal(L, "my_table"); // 获取表 lua_pushnil(L); // 初始键 while (lua_next(L, -2)) { // 遍历 printf("Key: %s, Value: %s\n", lua_tostring(L, -2), lua_tostring(L, -1)); lua_pop(L, 1); // 移除值,保留键 }
辅助库函数(luaL_*
)
8. luaL_len(L, index)
- 作用:直接返回值的长度(整数)。
- 代码示例:
lua_pushstring(L, "Lua"); lua_Integer len = luaL_len(L, -1); // len = 3
9. luaL_loadbuffer(L, buff, sz, name)
- 作用:从内存加载代码。
- 代码示例:
const char *code = "print('Hello from buffer!')"; if (luaL_loadbuffer(L, code, strlen(code), "buffer") == LUA_OK) { lua_pcall(L, 0, 0, 0); // 输出 Hello from buffer! }
10. luaL_loadbufferx
- 作用:同
luaL_loadbuffer
,支持模式(如二进制)。 - 代码示例:
luaL_loadbufferx(L, code, size, "chunk", "b"); // 加载二进制块
11. luaL_loadfile
- 作用:加载文件中的代码。
- 代码示例:
if (luaL_loadfile(L, "script.lua") == LUA_OK) { lua_pcall(L, 0, 0, 0); // 执行文件 }
12. luaL_loadfilex
- 作用:支持指定加载模式的文件加载。
- 代码示例:
luaL_loadfilex(L, "precompiled.luac", "b"); // 加载二进制文件
13. luaL_loadstring
- 作用:从字符串加载代码。
- 代码示例:
luaL_loadstring(L, "return 1 + 1"); lua_pcall(L, 0, 1, 0); // 返回2
14. luaL_newlib
- 作用:创建并注册库函数表。
- 代码示例:
static const luaL_Reg mylib[] = { {"add", [](lua_State *L) { int a = luaL_checkinteger(L, 1); int b = luaL_checkinteger(L, 2); lua_pushinteger(L, a + b); return 1; }}, {NULL, NULL} }; luaL_newlib(L, mylib); // 创建表并注册函数 lua_setglobal(L, "mylib"); // 全局名为 mylib
15. luaL_newlibtable
- 作用:创建空表供后续填充。
- 代码示例:
luaL_newlibtable(L, mylib); // 仅创建空表 luaL_setfuncs(L, mylib, 0); // 手动注册函数
16. luaL_newmetatable
- 作用:创建或获取元表。
- 代码示例:
if (luaL_newmetatable(L, "MyType")) { // 新建元表 lua_pushcfunction(L, [](lua_State *L) { // __gc 方法 MyData *d = (MyData*)lua_touserdata(L, 1); free(d); // 清理资源 return 0; }); lua_setfield(L, -2, "__gc"); // 设置元方法 }
关键整合示例
用户数据与元表
// 定义类型
typedef struct { int val; } MyType;
// 元表方法
static const luaL_Reg mytype_methods[] = {
{"get", [](lua_State *L) {
MyType *mt = (MyType*)luaL_checkudata(L, 1, "MyType");
lua_pushinteger(L, mt->val);
return 1;
}},
{NULL, NULL}
};
// 注册类型
int luaopen_mytype(lua_State *L) {
luaL_newmetatable(L, "MyType"); // 创建元表
luaL_newlib(L, mytype_methods); // 注册方法
lua_setfield(L, -2, "__index"); // 元表.__index = 方法表
lua_pushcfunction(L, [](lua_State *L) { // 构造函数
MyType *mt = (MyType*)lua_newuserdata(L, sizeof(MyType));
mt->val = luaL_checkinteger(L, 1);
luaL_getmetatable(L, "MyType");
lua_setmetatable(L, -2);
return 1;
});
return 1;
}
协程调度
lua_State *co = lua_newthread(L); // 创建协程
luaL_loadstring(co, "coroutine.yield(1); coroutine.yield(2)"); // 加载代码
int res;
do {
res = lua_resume(co, L, 0); // 恢复执行
printf("Yielded: %d\n", lua_tointeger(co, -1));
} while (res == LUA_YIELD);
总结
- 虚拟机管理:
lua_newstate
创建独立环境,需手动管理内存。 - 数据操作:
lua_newtable
、lua_newuserdata
结合元表实现复杂结构。 - 代码加载:
luaL_load*
系列加载代码,需显式调用lua_pcall
执行。 - 协程:
lua_newthread
创建轻量级线程,通过lua_resume
控制执行。
正确使用这些函数能高效嵌入 Lua 到 C/C++ 项目中,实现灵活的脚本扩展。