首页 > 解决方案 > 如何在与 LUA 脚本一起使用的 lambda 中引用“this”

问题描述

我正在尝试将 LUA API 添加到我的 C++ 程序中,并且我正在尝试允许脚本绘制到我的 GUI。到目前为止,我的 lambda 函数有这个:

auto addToDrawList = [](lua_State* L) -> int
{
    int DrawType = (int)lua_tonumber(L, -2);
    std::string Label = (std::string)lua_tostring(L, -1);

    bool found = false;
    for (int i = 0; i <= DrawList.size(); i++)
    {
        if (DrawList[i].Active == false && !found)
        {
            switch (DrawType)
            {
            case(0):
                break;
            case(1):
                DrawList[i].Active = true;
                DrawList[i].DrawType = Type::TextBox;
                DrawList[i].Label = Label;
                break;
            }
            found = true;
        }
    }

    return 0;
};

这是我正在运行的 LUA 脚本:

const char* LUA_FILE = R"(
    addToDrawList(1, "Test")
)";

这就是我将函数推送到 LUA 堆栈的方式:

lua_State* L = luaL_newstate();

lua_newtable(L);
int uiTableInd = lua_gettop(L);
lua_pushvalue(L, uiTableInd);
lua_setglobal(L, "Ui");

lua_pushcfunction(L, addToDrawList);
lua_setfield(L, -2, "addToDrawList");

问题出在我的第一个脚本中,因为它无法将 'DrawList' 数组作为this.

因此,为了解决它,我尝试this通过执行以下操作添加到 lambda 的捕获列表中:

auto addToDrawList = [this](lua_State* L) -> int

这似乎可以工作并解决错误,但后来我遇到了最后一个脚本的问题:

lua_pushcfunction(L, addToDrawList);

错误

我一直在 Internet 上搜索修复程序,但找不到任何解决方法。

标签: c++lua

解决方案


lua_pushcfunction()采用 C 风格的函数指针。无捕获的lambda 可以转换为这样的函数指针,但捕获的lambda 不能。

请改用1。它将允许您将用户定义的值(称为upvalues)与 C 函数相关联,例如您的指针,或者只是指向 的指针等。lua_pushcclosure()thisDrawList

创建 C 函数时,可以将一些值与其关联,从而创建 C 闭包(参见§3.4);然后,无论何时调用该函数,都可以访问这些值。要将值与 C 函数关联,首先应将这些值压入堆栈(当有多个值时,首先压入第一个值)。然后lua_pushcclosure调用创建 C 函数并将其压入堆栈,参数n告诉函数应该与多少值相关联。lua_pushcclosure还会从堆栈中弹出这些值。

1:lua_pushcfunction()只是lua_pushcclosure()定义了 0 个上值的包装器。

例如:

auto addToDrawList = [](lua_State* L) -> int
{
    const MyClassType *pThis = (const MyClassType*) lua_topointer(L, lua_upvalueindex(1));

    // use pThis->DrawList as needed...

    return 0;
};

...

lua_State* L = luaL_newstate();
...
//lua_pushcfunction(L, addToDrawList);
lua_pushlightuserdata(L, this);
lua_pushcclosure(L, addToDrawList, 1);
...

推荐阅读