KEEP K.I.S.S.

tk's blog

用 C 扩展写 Lua closure

tk posted @ May 30, 2012 07:30:28 PM in Lua , 4124 阅读

这个是《programming in lua》中的有的一个例子,通过 closure(闭包)来实现一个 tuple(元组)。

元组是一种具有匿名字段的常量记录。可以用一个数字索引来检索某个字段,或者一次性检索所有字段。

这里的实现将元组表示为函数,元组的值存放在函数绑定的 upvalue 中。大概的 Lua 代码示意如下:

local tuple = {}
function tuple.new(...)
    local t = {...}
    return function(index)
        if index then
            if type(index) ~= "number" then error("invalid index type") end
            if index < 0 then error("index is out of range") end
            return t[index]            
        else
            return unpack(t)
        end
    end
end

闭包工厂 tuple.new 中的 table t 就是用于存放元组内容的 upvalue,这个 tuple 的使用如下:

local x = tuple.new(10, "hi", {}, 4)
print(x(1))
print(x(2))
print(x())

当用一个数字参数来调用此函数时,它会返回指定的字段。当不用参数来调用此函数时,则返回所有的字段。输出为:

10
hi
10 hi table: 0041B870 4
 
下面使用 Lua 的 C 扩展来实现这个 tuple:
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

static int
t_tuple(lua_State *L) 
{
    int op = luaL_optint(L, 1, 0);
    if (op == 0) { /* 无参数? */
        int i;
        /* 将所有合法 upvalue 压入栈中 */
        for (i = 1; !lua_isnone(L, lua_upvalueindex(i)); i++)
            lua_pushvalue(L, lua_upvalueindex(i));

        return i - 1; /* 栈中值的数量 */
    }
    else { /* 获取 'op' 字段 */
        luaL_argcheck(L, 0 < op, 1, "index out of range");
        if (lua_isnone(L, lua_upvalueindex(op))) { /* 无此字段 */
            lua_pushnil(L);  /* 返回 nil 表明不存在 */
            return 1;
        }
        lua_pushvalue(L, lua_upvalueindex(op));
        return 1;
    }
}

static int 
t_new(lua_State *L)
{
    lua_pushcclosure(L, t_tuple, lua_gettop(L));
    return 1;
}

static const struct luaL_Reg tuplelib[] = {
    {"new", t_new},
    {NULL, NULL}
};

int luaopen_tuple(lua_State *L)
{
    luaL_register(L, "tuple", tuplelib);
    return 1;
}

编译成“tuple.dll”(windows 下)然后仍然用上面的 tuple 使用代码测试,不过要先“require 'tuple'”来加载这个扩展。DLL 中的需要导出 lutopen_tuple 这个函数符号。

t_new 是创建元组的工厂函数。将需要作为 upvalue 的参数实现压入栈中,然后调用 lua_pushcclosure 来创建一个基于 t_tuple 的 closure 。lua_gettop 返回栈的大小,在这里也就等于已经压入栈中作为 upvalue 的数量。lua_upvalueindex 是一个用来索引 upvalue 的宏,当索引一个不存在的 upvalue ,结果会是一个类型为 LUA_TNONE 的伪值(pseudo-value),当索引超出当前栈范围时候,也会得到这样的 LUA_TNONE 的伪值。不能以负数来调用 lua_upvalueindex ,所以做了范围检查,luaL_argcheck(L, 0 < op, 1, "index out of range") 第二个参数是个条件表达式,第三个是检查的参数数量,最后一个是检查失败传递的消息。

用于检测可选参数的函数是 luaL_optint ,它允许参数不存在,如果不存在,则返回一个指定的默认值,也就是最后一个参数。

  • 无匹配
  • 无匹配
لی ویوسوہ ہو یار 说:
Jul 26, 2021 01:14:32 AM

Your content is nothing short of brilliant in many ways. I think this is engaging and eye-opening material. Thank you so much for caring about your content and your readers. soap2day safe

لی ویوسوہ ہو یار 说:
Jul 27, 2021 01:22:07 AM

You make so many great points here that I read your article a couple of times. Your views are in accordance with my own for the most part. This is great content for your readers. second hand gaming pc

لی ویوسوہ ہو یار 说:
Jul 27, 2021 03:20:17 PM

Thank you for such a well written article. It’s full of insightful information and entertaining descriptions. Your point of view is the best among many. hts 임대

لی ویوسوہ ہو یار 说:
Jul 30, 2021 11:44:57 PM

I can set up my new idea from this post. It gives in depth information. Thanks for this valuable information for all,.. תיקון פאצ

لی ویوسوہ ہو یار 说:
Jul 31, 2021 09:18:14 PM

You have a real ability for writing unique content. I like how you think and the way you represent your views in this article. I agree with your way of thinking. Thank you for sharing. rantai qq

لی ویوسوہ ہو یار 说:
Jul 31, 2021 09:37:46 PM

hello!! Very interesting discussion glad that I came across such informative post. Keep up the good work friend. Glad to be part of your net community. https://kctapp.com/

seoservvise 说:
Aug 05, 2021 09:29:50 PM

What a fantabulous post this has been. Never seen this kind of useful post. I am grateful to you and expect more number of posts like these. Thank you very much. what is smite

لی ویوسوہ ہو یار 说:
Aug 24, 2021 02:21:20 PM

I use only high quality materials - you can see them at: also visit

seoservise 说:
Dec 09, 2021 10:07:29 PM

This is a good post. This post gives truly quality information. I’m definitely going to look into it. Really very useful tips are provided here. Thank you so much. Keep up the good works. lottery sambad

Alice 说:
Feb 22, 2022 09:00:46 PM

You have a real ability for writing unique content. I like how you think and the way you represent your views in this article. I agree with your way of thinking. Thank you for sharing. <a href="https://devpost.com/talano9287">Find the best font</a>

PHuket DMC 说:
Jan 09, 2023 03:00:46 AM

I feel very grateful that I read this. It is very helpful and very informative and I really learned a lot from it. PHuket DMC

Natrium Pentobarbita 说:
Feb 19, 2023 01:05:20 AM

Through this post, I know that your good knowledge in playing with all the pieces was very helpful. I notify that this is the first place where I find issues I've been searching for. You have a clever yet attractive way of writing. Natrium Pentobarbital Kaufen

Ms. Marvel Kamala Kh 说:
Apr 26, 2023 02:29:31 AM

Cool stuff you have and you keep overhaul every one of us Ms. Marvel Kamala Khan Denim Jacket

tech 说:
Dec 06, 2023 01:19:38 AM

With so many books and articles coming up to give gateway to make-money-online field and confusing reader even more on the actual way of earning money, UFABETโปรโมชั่นเว็บบอล


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter