Lua 基础 API与 辅助库函数 中关于创建的方法用法
目录
- 基础 API 函数
- 1. `lua_len(L, index)`
- 2. `lua_load(L, reader, data, chunkname, mode)`
- 3. `lua_newstate(allocator, ud)`
- 4. `lua_newtable(L)`
- 5. `lua_newthread(L)`
- 6. `lua_newuserdata(L, size)`
- 7. `lua_next(L, index)`
- 辅助库函数(`luaL_*`)
- 8. `luaL_len(L, index)`
- 9. `luaL_loadbuffer(L, buff, sz, name)`
- 10. `luaL_loadbufferx`
- 11. `luaL_loadfile`
- 12. `luaL_loadfilex`
- 13. `luaL_loadstring`
- 14. `luaL_newlib`
- 15. `luaL_newlibtable`
- 16. `luaL_newmetatable`
- 关键整合示例
- 用户数据与元表
- 协程调度
- 总结
基础 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); // 执行代码,返回42printf("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++ 项目中,实现灵活的脚本扩展。