Lua与C/C++的交互3:C/C++中读取Lua文件中的表

在第二章中,我在vs中通过用c/c++调用跟lua交互的C API,成功读取了lua配置文件中的内容:一个全局变量。这次,我要稍微深入一点:在lua文件中定义一个表,然后用C/C++读取表中的内容。这个其实跟第二章原理是一样的,只是,这里有个细节,这个细节就是lua_getfield. 以下是完整源代码:

#include "stdafx.h"
#include "stdio.h"
extern "C"
{
	#include "lua.h"
	#include "lualib.h"
	#include "lauxlib.h"
};

#pragma comment(lib,"lua5.1.lib")

void stackDump(lua_State *L)
{
	int i;
	int top = lua_gettop(L);
	printf("the size of stack is:%d\n",top);
	for ( i = 1;i <= top;i++ )
	{
		int type = lua_type(L, i);
		switch(type)
		{
		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;
			}
		case LUA_TTABLE:
			{
				printf("this is a table!");
				break;
			}
		default:
			{
				printf("%s",lua_typename(L ,i));
				break;
			}
		}
		printf(" ");
	}
	printf("\n");
}

//获取lua文件中类型为表的变量
void loadConfigTable(lua_State *L,const char *fname, int *w, int *h)
{
	if ( luaL_loadfile(L, fname) || lua_pcall(L,0,0,0) )
		printf("error,can't run config file:%s:",lua_tostring(L,-1));
	stackDump(L);
	lua_getglobal(L, "color");	//获取lua文件中的表color,压入栈顶
	if ( !lua_istable(L, -1) ) 
		printf("error,color is not a table");
	stackDump(L);
	lua_getfield(L, -1, "red");	//获取color表中key为red的value。获取前color表位于栈顶
	if ( !lua_isnumber(L,-1) )
		printf("error,color type is not a number");
	stackDump(L);
	*w = lua_tointeger(L, -1);
	lua_pop(L, 1);				//从栈中弹出一个元素,即弹出栈顶值
	lua_getfield(L, -1, "white");
	if ( !lua_isnumber(L, -1) )
		printf("error,color type is not a number");
	stackDump(L);
	*h = lua_tointeger(L, -1);
}

int _tmain(int argc, _TCHAR* argv[])
{
	lua_State *L;
	L = luaL_newstate();
	luaL_openlibs(L);	
	int i = 0;
	int j = 0;
	loadConfigTable(L, "configTable.lua", &i, &j);
	printf("the value of i,j is %d,%d",i,j);
	return 0;
}
打印信息如下:

the size of stack is:0

the size of stack is:1
this is a table!
the size of stack is:2
this is a table! 1
the size of stack is:2
this is a table! 4
the value of i,j is 1,4

其中configTable.lua文件内容如下:

color = {red = 1,green = 2,yellow = 3,white = 4,brown = 5}

详细讲解下lua_getfield(lua_State *L, int idx, const char *k),这个函数用以获取表中对应key的value。其中参数idx是表在栈中的位置,k是表中的key。其实它就相当于这两个函数的组合,lua_pushstring(L, key) && lua_gettable(L, idx),这里key必须位于栈顶。所以要想获取栈中表对于key的value,我们需要把key压入栈顶,然后通过lua_gettable(L, idx)弹出栈顶key,同时将key对应的value压入栈顶。
在上面的程序中,先用lua_getglobal(l, "color")获取lua中的表color后压入栈顶,现在栈顶的值是一个表。接着调用lua_getfield(L, -1, "red"),此时表位于栈顶,所以idx为-1,调用过程是,red先被压入栈顶,然后从栈顶弹出,栈顶元素被red对应的value,即1取代。现在栈顶值为1,栈底值为table,接着lua_pop后,继续获取表中其他key对应的value。
详细描述Lua和C之间相互传递Table类型数据 /* ====================================================== */ // 遍历Lua传入的Table类型参数, 获取它的Key/Value, 其关键操作是 lua_next() // lua_next() 返回1读取成功,返回0示已经没有数据可读了 // lua_next() 会使用栈顶元素作为Key去定位本次需要取出Table里面的那个值对 // 如果Key=nil, 那就示本次取出的是第一个元素 // 它会先将当前的这个Key弹出,然后将本次取出的Key/Value压入栈, Value在栈顶 // 一个比较隐晦的处理就是, 我们不应直接使用lua_tostring(L, -2)来读取Key // 因为lua_tostring()在Key类型不是字符串时, 它会修改栈上的Key数据 // 这样, 下次调用lua_next()时, 就会因为Key被修改了而导致错误 // 为此,先调用lua_pushvalue(L, -2),将它Copy一份到栈顶,对这个Copy进行lua_tostring() // 读取Key,Value到C变量里面后,将Value和Copy弹出,留着Key在栈顶,给下次lua_next()用 // // 指令及栈图变化如下: (假如Table的栈下标是Index) // 0. 刚进入函数时 ...Table, ... <--- 这里栈顶 // 1. lua_pushnil(L) ...Table, ..., nil <--- 这里栈顶 // 2. lua_next(L, Index) ...Table, ..., Key, Value <--- 这里栈顶 // 3. lua_pushvalue(L, -2) ...Table, ..., Key, Value, KeyCopy <--- 这里栈顶 // 4. lua_pop(L, 2), ...Table, ..., Key <--- 这里栈顶 // ... 如此重复2,3,4 // N. lua_next(L, Index)返回0 ...Table, ... <--- 这里栈顶 /* ====================================================== */
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值