位置:首页 > Lua > iOS 调用 Lua:方法传递、返回值与数组字典映射说明

iOS 调用 Lua:方法传递、返回值与数组字典映射说明

时间:2026-08-25  |  作者:半糖攻略君  |  阅读:0

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

6 方法的传递

Lua中只能接受C定义的方法传入,并且方法的声明必须符合lua_CFunction函数指针的定义,即:

int functionName (lua_State *state);

那么,传入方法则需要先定义一个C语言声明的方法,如:

int printHelloWorld (lua_State *state)
{
    NSLog(@"Hello World!");
    return 0;
}

方法里面简单地进行了一下信息打印,其中方法的返回值是一个整数,表明了该方法需要返回多少个值到Lua中(后续章节会进行返回值的相关演示),现在不需要返回值则为0。然后,再通过lua_pushcfunction方法将方法传入:

lua_pushcfunction(self.state, printHelloWorld);
lua_setglobal(self.state, "funcVal");

操作完成后,在Lua中就可以直接调用了:

funcVal();

如果定义的方法是允许接受参数的,那么可以从state参数里面获取传入的参数。拿上面的例子,例如方法接收一个名字的字符串参数,函数的代码则可以修改为:

int printHelloWorld (lua_State *state)
{
    if (lua_gettop(state) > 0)
    {
        //表示有参数
        const char *name = lua_tostring(state, 1);
        NSLog(@"Hello %s!", name);
    }

    return 0;
}

然后在Lua中则可以这样调用:

funcVal ("vimfung");

要是定义的方法并非直接打印字符串,而是将字符串组合后返回给Lua,那在定义的方法里就得配合’lua_pushXXXX’系列方法来传递返回值。这里要特别留意:方法中return的数量必须和push到栈中的值一致,不然可能会出现异常情况。 如此一来,上面定义的函数就可以像下面这样修改:

int printHelloWorld (lua_State *state)
{
    if (lua_gettop(state) > 0)
    {
        //表示有参数
        const char *name = lua_tostring(state, 1);

        //入栈返回值
        NSString *retVal = [NSString stringWithFormat:@"Hello %s!", name];
        lua_pushstring(state, retVal.UTF8String);

        return 1;
    }

    return 0;
}

然后在Lua中则可以这样调用:

local retVal = funcVal("vimfung");
print(retVal);

7 数组和字典的传递

在Lua中,数组(Array)和字典(Dictionary)都由一个Table类型所表示(在Lua看来数组其实也属于一种字典,只是它的key是有序并且为整数)。如:

-- 定义数组
local arrayVal = {1,2,3,4,5,6};
-- 定义字典
local dictVal = {a=1, b=3, c=4, d=5};

上面的例子分别用了不带key的声明和带key的声明两种方式来创建Table类型。其中不带key的声明方式,解析器会默认为其创建一个key,该key是从1开始,由小到大进行分配,其等效于:

local arrayVal = {1=1, 2=2, 3=3, 4=4, 5=5, 6=6};

当然,两种方式是可以混合使用,如:

local tbl = {1, 2, a=1, b=2, 3};

Table属于比较复杂的数据结构,因此提供操作它的C Api也比较复杂,下面将根据数组和字典分别讲述它们的传递方式。

7.1 数组传递

首先,需要将一个Table类型入栈,这样才能对其进行进一步的操作。由于没有pushtable这样的方法,但是可以使用lua_newtable来创建一个Table对象,并且该对象会自动放入栈顶位置。如:

lua_newtable(self.state);

然后对要传递的数组进行遍历,并通过lua_rawseti方法将元素值设置到Table中。如:

NSArray *array = @[@1, @2, @3, @4, @5, @6];
 [array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

    NSInteger value = [obj integerValue];
    lua_pushinteger(self.state, value);
    lua_rawseti(self.state, -2, idx + 1);

}];

lua_getglobal(self.state, "arrayVal");

借助上述代码,就能把一个数组传递给arrayVal变量。需特别留意:lua_rawseti方法用于将栈顶元素设置给指定Table对象的指定索引。其中,第二个参数代表Table对象在栈中的位置,第三个参数表示在Table中的索引,通常索引从1开始计数,所以上述代码中的idx需加1。如此操作后,栈顶元素会被移除。具体情况如下图所示:

image.png

7.2 字典传递

字典的传递同样需要先入栈一个Table:

lua_newtable(self.state);

然后对要传递的字典进行遍历,并通过lua_setfield方法将元素设置到Table中。如:

[dict enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {

    NSInteger value = [obj integerValue];
    lua_pushinteger(self.state, value);
    lua_setfield(self.state, -2, key.UTF8String);

}];

lua_setglobal(self.state, "dictVal");

lua_setfieldlua_rawseti功能类型,都是把一个元素放入Table中,只是一个用于指定整数索引,一个是指定字符串索引。通过上面的方式就可以把字典传递给Lua了。

《夸克》非常好用的免费AI浏览器

下载APP查看

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多