保留 Lua 状态在 C++ 环境中以限制上下文切换

我正在编写简单的 OpenGL 演示,并且最近决定在我的 C++ 引擎中使用 Lua,以便在不需要编译我的项目的情况下动态更改渲染。因此,我可以更轻松地调整渲染算法。但是我知道我的当前渲染更新函数可能远不够高效。

目前,我将一个矩阵从 C++ 转移到 Lua,使用 Lua 脚本对其进行修改,然后将其发送回我的 C++ 渲染引擎。但是每次从 C++ 引擎接收到更新调用时,我都重新加载 Lua 脚本,并且会丢失所有变量的上下文。这意味着我总是从头开始,而我的渲染离平滑还有很远的路要走。我在下面附上了一些示例代码以解释我正在做什么。我正在通过嵌入 C++ 学习 Lua,因此我知道我仍然没有掌握最佳实践。

update.lua

function transform(m)
    amplitude = 1.5
    frequency = 500
    phase = 0.0
    r = {}

    for i = 1, #m do
        r[i] = {}
        for j = 1, #m[i] do
            if (i % 2) then
                r[i][j] = amplitude * math.sin(m[i][j] + phase)
            else
                r[i][j] = -amplitude * math.sin(m[i][j] + phase)
            end
            phase = phase + 0.001
        end
    end
    return r
end

-- 由 C++ 调用
function update()
    m = pull()
    r  = transform(m)
    push(r)
end

matrix.cpp

// 从 Lua 视角拉取矩阵
static int pull(lua_State * _L)
{
    _push(_L, &_m);

    return 1;
}

// 从 Lua 视角推送矩阵
static int push(lua_State * _L)
{
    // 获取参数数量
    int n = lua_gettop(_L);

    if(1 == n) {
        _pull(_L, 1, &_m);
    }

    return 1;
}

void matrix::load_file(char * file, char * function)
{
    int status;

    // 加载包含要运行的脚本的文件
    status = luaL_loadfile(_L, file);
    switch (status) {
    case LUA_OK:
        break;
    case LUA_ERRFILE:
        std::cout << "LUA_ERRFILE: " << lua_error(_L) << std::endl;
        break;
    case LUA_ERRSYNTAX:
        std::cout << "LUA_ERRSYNTAX: " << lua_error(_L) << std::endl;
        break;
    default:
        std::cout << lua_error(_L) << std::endl;
    }

    lua_getglobal(_L, function);
    status = lua_pcall(_L, 1, 1, 0);
    if (status != LUA_OK) {
        std::cout << "error running file" << lua_error(_L) << std::endl;
    }
}

void matrix::update()
{
    load_file("lua/update.lua", "update");
}

我正在考虑在调用 update() 函数时传递一些参数,但我想知道 C++ 到 Lua 再到 C++ 的方法是否正确且高效。特别是考虑到我可能要在 Lua 中传输和修改巨大的矩阵。我可能缺少一些嵌入式 Lua 知识才能在加载脚本时保留上下文。您对我如何改进代码有何通用建议吗?我知道我目前的方法太复杂了。

点赞
用户1548468
用户1548468

一个快速的解决方法是,只有文件自上一帧以来被修改过才会被加载:

static time_t last_modified = 0;
struct stat sbuf;
stat(file, &sbuf);
if (sbuf.st_mtime > last_modified) {
    last_modified = sbuf.st_mtime;
    status = luaL_loadfile(_L, file);
    // 等等
}

// 现在调用函数
lua_getglobal(_L, function);
status = lua_pcall(_L, 1, 1, 0);
2020-05-06 08:20:54