【问题标题】:Invoking Lua functions the Python way i.e. named arguments以 Python 方式调用 Lua 函数,即命名参数
【发布时间】:2016-07-01 14:49:09
【问题描述】:

我有大约 50 多个 C++ 函数,它们接受固定数量的参数,比如 25 多个。将这些参数视为数据结构中的成员。

每个函数都实现了一个业务逻辑,它可能需要也可能不需要读取/检查所有 25 个参数的值。因此,一些函数可能只对 2 个值感兴趣,而其他有多个检查的函数可能会查找 15+。

一些示例函数如下:

C++

void DrawSegment(int length);
void DrawCircle(int radius);
void DrawRectangle(int width, int height);
void DrawCube(int side);

我的任务是在 Lua 中提供一个易于使用的接口方法来调用这些函数。类似的,

DrawShape("CIRCLE", 20)
DrawShape("RECTANGLE", 10, 20)

Lua-C++ 绑定代码:

enum TYPE{SEGMENT, CIRCLE, RECTANGLE, CUBE};

lua_Integer MapStringToEnum(const char*);

int lua_DrawShape(lua_State*L)
{
        lua_Integer type = MapStringToEnum(lua_tointeger(L, -1));
        switch (type)
        {
        case SEGMENT:
                DrawSegment(lua_tointeger(L, -2)); // length
                break;
        case CIRCLE:
                DrawCircle(lua_tointeger(L, -2));  // radius
                break;
        case RECTANGLE:
                DrawCircle(lua_tointeger(L, -2), lua_tointeger(L, -3)); // width, height
                break;
                ...
                //and so on for other types
        default:
                ASSERT(0);
        };
}

initShapeLibrary(lua_State* L)
{
    lua_pushcfunction(L, lua_DrawShape);
    lua_setglobal(L, "DrawShape");
}

我面临的挑战是,由于每个函数不需要所有参数,我如何让用户更容易指定这些字段?一种方法是记录参数及其顺序并期望用户遵循它。但这只会导致不可读的代码强制用户为他不打算传递的参数指定空值或空字符串。

-- 1st argument is radius, 2nd unused.
DrawShape("CIRCLE", 20, -1) 

这对代码不友好。我真正想要的是一个类似 Python 的工具,它允许代码可读。

DrawShape("CIRCLE", Radius=20)

有没有办法通过 Lua 实现这一点?如果没有,我打算对参数字符串进行标记,然后设置各个参数值​​。

您的反馈会有所帮助。非常感谢。

【问题讨论】:

    标签: c++ lua


    【解决方案1】:

    DrawShape("CIRCLE", Radius=20)

    您可以传递一个表格,这将允许您区分位置参数和命名参数:

    DrawShape({"CIRCLE", Radius=20})
    

    在这种情况下,您还可以使用允许您删除一对括号的语法糖:

    DrawShape{"CIRCLE", Radius=20}
    

    然后您可以使用unpack(t) 获取位置参数(假设t 是您传递的表参数)并使用t.Radius 获取其余参数或使用pairs 迭代它们。

    就我个人而言,我还是会坚持DrawCubeDrawCircle...

    【讨论】:

    • 使用表格是一个很酷的技巧! 'unpack' 似乎仅限于 Lua。对于 C++ 部分,我可能需要走桌子。对吗?
    • 是的,您可以使用pairs 遍历表中的元素,或使用for 循环访问位置元素,其中ipairs1, #t 范围。
    猜你喜欢
    • 2012-11-05
    • 1970-01-01
    • 1970-01-01
    • 2015-08-20
    • 2014-09-11
    • 2016-02-16
    • 2015-07-29
    • 2017-09-29
    • 2012-06-02
    相关资源
    最近更新 更多