前面介绍了当lua
文件做配置使用时,该如何使用 API 接口去获取配置文件信息, lua 文件作为配置文件使用还是比较方便的,解析程序也比较容易编写,但是前文只介绍了如何 k-v
类型的配置,意味着 k 不能相同。所以本文介绍更高级的使用方式,本人将介绍如何利用lua中的数据结构table
来作为配置文件,并在最后介绍 C 如何调用 lua 中的函数。
前言
table
作为 lua 语言中的一种数据结构,相对于 C/C++ 语言而言,简直就是 bug 一般的存在,使用真是太方便了,其组合简单易用,可以任意组合成不同的类型 table。本文就介绍如何操作 table 的 API,并示例使用table作为配置数据。
API
下面介绍操作 table
的AP
获取table元素
int lua_getfield (lua_State *L, int index, const char *k);
作用:把 t[k] 的值压栈,这里的 t 是索引指向的值
设置table元素
void lua_setfield (lua_State *L, int index, const char *k);
作用:做一个等价于 t[k] = v 的操作,这里 t 是给出的索引处的值, 而 v 是栈顶的那个值
下面介绍其他相关的函数
判断栈中值得类型
int lua_istable (lua_State *L, int index);
作用:当给定索引的值是一张表时,返回 1 ,否则返回 0 。
int lua_isfunction (lua_State *L, int index);
作用:当给定索引的值是一个函数( C 或 Lua 函数均可)时,返回 1 ,否则返回 0 。
将指定索引值转换成字符串
int lua_isfunction (lua_State *L, int index);
作用:当给定索引的值是一个函数( C 或 Lua 函数均可)时,返回 1 ,否则返回 0 。
示例
/*
* gcc test.c -llua -lm -ldl
*/
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdio.h>
/*
* 从栈底到栈顶依次遍历整个堆栈
*/
static void stackDump(lua_State* L)
{
int i;
int top = lua_gettop(L);
for(i = 1; i <= top; ++i)
{
int t = lua_type(L, i);
switch(t)
{
case LUA_TSTRING:
printf("'%s'", lua_tostring(L, i));
break;
case LUA_TBOOLEAN:
printf(lua_toboolean(L, i) ? "true": "false");
break;
case LUA_TNUMBER:
printf("'%g'", lua_tonumber(L, i));
break;
default:
printf("'%s'", lua_typename(L, t));
break;
}
printf(" ");
}
printf("\n");
}
void PrintfLuaType(lua_State* L, int type)
{
printf("'%s'", lua_typename(L, type));
}
int main(int argc, char *argv[])
{
lua_State *L = lua_open();
luaL_openlibs(L);
//加载配置文件
int iRet = luaL_loadfile(L, "config.lua");
if(iRet)
{
printf("laodfile config.lua fail!!\n");
lua_close(L);
return 0;
}
iRet = lua_pcall(L, 0, 0, 0);
if(iRet)
{
printf("lua_pcall fail!!\n");
lua_close(L);
return 0;
}
lua_getglobal(L, "color");
stackDump(L);
if(!lua_istable(L, -1))
{
printf("It's not table\n");
lua_close(L);
return 0;
}
//读取table中字段的值,将值压入栈,因此下一个获取值时,table的index已经改变了
lua_getfield(L, -1, "r");
lua_getfield(L, -2, "g");
lua_getfield(L, -3, "b");
stackDump(L);
if(!lua_isnumber(L, -3))
{
printf("r is not number\n");
lua_close(L);
return 0;
}
if(!lua_isnumber(L, -2))
{
printf("g is not number\n");
lua_close(L);
return 0;
}
if(!lua_isnumber(L, -1))
{
printf("b is not number\n");
lua_close(L);
return 0;
}
int r = lua_tointeger(L, -3);
int g = lua_tointeger(L, -2);
int b = lua_tointeger(L, -1);
printf("r[%d] g[%d] b[%d]\n", r, g, b);
//调用函数
lua_getglobal(L, "add");
if(!lua_isfunction(L, -1))
{
printf("It's not function\n");
lua_close(L);
return 0;
}
//压入参数
lua_pushnumber(L, 10); //第一个参数
lua_pushnumber(L, 20); //第二个参数
iRet = lua_pcall(L, 2, 1, 0);
if(iRet)
{
printf("%s\n", lua_tostring(L, -1));
lua_close(L);
return 0;
}
if(!lua_isnumber(L, -1))
{
printf("Result is not number\n");
lua_close(L);
return 0;
}
iRet = lua_tonumber(L, -1);
printf("Ret[%d]\n", iRet);
lua_close(L);
return 0;
}
lua文件为:
color = {r=128, g=123, b=255}
function add(iA, iB)
return iA + iB
end
编译执行后结果为:
'table'
'table' '128' '123' '255'
r[128] g[123] b[255]
Ret[30]
总结
lua中table的操作,本文只是介绍简单的结构,table可以互相嵌套组成比较复杂的结构,操作的时候也需要相当的注意。对于API的细节不料及的可以查阅手册,如何设置table中的值,本文只给出了API介绍,并未给出示例,有兴趣的可以自己去尝试下。多多写写代码总归是好的,看得过瘾不如自己找个bug解决来得爽。
网友评论