一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
2 获取布尔值
与获取数值相同,通过lua_toboolean方法来获取某个布尔变量的值。如:
lua_getglobal(self.state, "aa");
BOOL value = lua_toboolean(self.state, -1);
if (value)
{
NSLog(@"aa = YES");
}
else
{
NSLog(@"aa = NO");
}
lua_pop(self.state, 1);
3 获取字符串
lua_tostring方法来获取字符串变量的值。如:
lua_getglobal(self.state, "aa");
const char *value = lua_tostring(self.state, -1);
NSLog(@"aa = %s", value);
lua_pop(self.state, 1);
4 获取二进制数组
lua_tolstring方法来获二进制数组变量的值。如:
lua_getglobal(self.state, "aa");
size_t len = 0;
const char *bytes = lua_tolstring(self.state, -1, &len);
NSData *data = [NSData dataWithBytes:bytes length:len];
NSLog(@"aa = %@", data);
lua_pop(self.state, 1);
5 方法的获取和调用
一般情况下,要获取Lua中的某个Function主要是用于对其进行调用。假设有一个Lua方法定义如下:
function printHelloWorld ()
print("Hello World");
end
那么,对应OC中需要下面的代码来获取和调用它:
lua_getglobal(self.state, "printHelloWorld");
lua_pcall(self.state, 0, 0, 0);
上述代码中的lua_pcall方法表示将栈中的元素视作Function来进行调用。其中第二个参数为传入参数的数量,必须与压栈的参数数量一致;第三个参数为返回值的数量,表示调用后其放入栈中的返回值有多少个。第四个参数是用于发生错误处理时的代码返回。其运行原理如下图所示:
对于带参数和返回值的方法,在获得方法对象后,需要调用lua_pushXXX系列方法来设置传入参数。可以参考下面例子:
假设有一个加法的Lua方法,其定义如下:
function add (a, b)
return a + b;
end
那么,OC中则可以进行下面操作来调用方法并传递参数,最终取得返回值然后打印到控制台:
lua_getglobal(self.state, "add");
lua_pushinteger(self.state, 1000);
lua_pushinteger(self.state, 24);
lua_pcall(self.state, 2, 1, 0);
NSInteger retVal = lua_tonumber(self.state, -1);
NSLog(@"retVal = %ld", retVal);
6 Table的获取和遍历
Table的获取跟其他变量一样,一旦放入栈后可以根据需要通过调用lua_getfield方法来指定的key的值。如:
//假设Lua中有一个Table变量aa = {key1=1000, key2=24};
lua_getglobal(self.state, "aa");
lua_getfield(self.state, -1, "key2");
NSInteger value = lua_tonumber(self.state, -1);
NSLog(@"value = %ld", value);
lua_pop(self.state, 1);
如果Table是声明时没有指定key,那么则需要调用lua_rawgeti来获取Table的值。如:
//假设Lua中有一个Table变量aa = {1000, 24};
lua_getglobal(self.state, "aa");
lua_rawgeti(self.state, -1, 2);
NSInteger value = lua_tonumber(self.state, -1);
NSLog(@"value = %ld", value);
lua_pop(self.state, 1);
有时候,Table存储的信息会在函数体外被访问,那么我们需要对Table进行遍历然后把它放入一个字典中,然后提供给程序使用。代码如下:
//假设Lua中有一个Table变量aa = {1000, 24};
lua_getglobal(self.state, "aa");
lua_pushnil(self.state);
while (lua_next(self.state, -2))
{
NSInteger value = lua_tonumber(self.state, -1);
if (lua_type(self.state, -2) == LUA_TSTRING)
{
const char *key = lua_tostring(self.state, -2);
NSLog(@"key = %s, value = %ld", key, value);
}
else if (lua_type(self.state, -2) == LUA_TNUMBER)
{
NSInteger key = lua_tonumber(self.state, -2);
NSLog(@"key = %ld, value = %ld", key, value);
}
lua_pop(self.state, 1);
}
上述代码利用lua_next方法来遍历Table的所有元素,该方法从栈顶弹出一个元素作为遍历Table的起始Key,然后把每个元素的Key和Value放入栈中。为了遍历所有元素所以起始的Key设置了一个nil值,证明要从Table最开始的Key进行遍历。如图:
值得注意的是,在获取Key值时,最好先判断Key的类型,然后再根据其对应类型调用相应的lua_toXXX方法。否则,因为lua_toXXX系列方法会对元素值进行类型转换,如整型的Key被lua_tostring转换为String后再给到lua_next进行遍历就会报找不到指定Key的错误。
7 获取自定义数据
利用lua_topointer方法来获取自定义数据,如:
lua_getglobal(self.state, "ud");
NSObject *obj = (__bridge User *)(lua_topointer(state, 1));
下面是实际操作:
需要一个lua文件来写我们的测试方法。直接新建一个txt记事本,将后缀名改为.lua即可,so easy。这个时候就需要在demo.lua中来写我们的测试方法了,简单实现一个加法运算。
function addFunc (add1, add2)
return add1 + add2;
end
创建lua_State对象L
通过luaL_dofile调用demo.lua文件
将方法名和参数入栈
通过调用lua_pcall方法调用lua中的addFun
返回值通过lua_tostring得到