c++ - Lua C API - 使用同名的变量和函数加载多个文件

标签 c++ lua embedded-language

假设我有两个 Lua 文件,我将从标准 Lua C API 使用它们,它们共享一个公共(public)库:

common.lua

function printHello(name)
    print("Hello from " .. name)
end

文件1.lua
require "common"
local scriptName = "file1"

function doSomething()
    printHello(scriptName)
end

文件2.lua
require "common"
local scriptName = "file2"

function doSomething()
    printHello(scriptName)
end

现在说我想让两个 file*.lua 文件共享 相同 lua_State . 无需更改任何 Lua 代码 , 我怎样才能加载文件以便我可以调用特定的 doSomething() ?

有没有办法可以将“所有内容”从加载的文件(函数、变量、表)中移动到 lua_State 中的全局表中?使用脚本名称(或其他)作为键?另外,有没有办法让 file1.lua 和 file2.lua 可以共享 common.lua 的“内存”版本?

我正在使用 Lua 5.1。

谢谢!

最佳答案

以下是在纯 Lua 5.1 中的操作方式:

file1_env = setmetatable({}, {__index = _G})
local file1_chunk = loadfile('file1.lua')
setfenv(file1_chunk, file1_env)
file1_chunk()

file2_env = setmetatable({}, {__index = _G})
local file2_chunk = loadfile('file2.lua')
setfenv(file2_chunk, file2_env)
file2_chunk()

file1_env.doSomething() -- prints "Hello from file1"
file2_env.doSomething() -- prints "Hello from file2"

发生的事情是您正在更改每个文件的 block 运行的环境,所以而不是把它们的 doSomething在全局环境中运行并因此相互踩踏,它们进入自己的本地环境(使用元表,因此它们可以使用全局环境中的东西,如 requireprint )。根据要求,common.lua只需要运行一次,你会看到你是否放了 printHello('common') 之类的东西最后。

如果您想从 C 中执行此操作,我使用的所有功能都可以直接转换为 C API,如下所示:

#include <lua5.1/lua.h>
#include <lua5.1/lualib.h>
#include <lua5.1/lauxlib.h>

int main(void) {
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);

    /* stack is empty */
    lua_createtable(L, 0, 1);
    /* -1: file1_env */
    lua_createtable(L, 0, 1);
    /* -2: file1_env, -1: file1_env_mt */
    lua_pushvalue(L, LUA_GLOBALSINDEX);
    /* -3: file1_env, -2: file1_env_mt, -1: _G */
    lua_setfield(L, -2, "__index");
    /* -2: file1_env, -1: file1_env_mt */
    lua_setmetatable(L, -2);
    /* -1: file1_env */
    luaL_loadfile(L, "file1.lua");
    /* -2: file1_env, -1: file1_chunk */
    lua_pushvalue(L, -2);
    /* -3: file1_env, -2: file1_chunk, -1: file1_env */
    lua_setfenv(L, -2);
    /* -2: file1_env, -1: file1_chunk */
    lua_call(L, 0, 0);
    /* -1: file1_env */
    lua_setglobal(L, "file1_env");
    /* stack is empty */
    lua_createtable(L, 0, 1);
    /* -1: file2_env */
    lua_createtable(L, 0, 1);
    /* -2: file2_env, -1: file2_env_mt */
    lua_pushvalue(L, LUA_GLOBALSINDEX);
    /* -3: file2_env, -2: file2_env_mt, -1: _G */
    lua_setfield(L, -2, "__index");
    /* -2: file2_env, -1: file2_env_mt */
    lua_setmetatable(L, -2);
    /* -1: file2_env */
    luaL_loadfile(L, "file2.lua");
    /* -2: file2_env, -1: file2_chunk */
    lua_pushvalue(L, -2);
    /* -3: file2_env, -2: file2_chunk, -1: file2_env */
    lua_setfenv(L, -2);
    /* -2: file2_env, -1: file2_chunk */
    lua_call(L, 0, 0);
    /* -1: file2_env */
    lua_setglobal(L, "file2_env");
    /* stack is empty */
    lua_getglobal(L, "file1_env");
    /* -1: file1_env */
    lua_getfield(L, -1, "doSomething");
    /* -2: file1_env, -1: file1_env.doSomething */
    lua_call(L, 0, 0);
    /* -1: file1_env */
    lua_pop(L, 1);
    /* stack is empty */
    lua_getglobal(L, "file2_env");
    /* -1: file2_env */
    lua_getfield(L, -1, "doSomething");
    /* -2: file2_env, -1: file2_env.doSomething */
    lua_call(L, 0, 0);
    /* -1: file2_env */
    lua_pop(L, 1);
    /* stack is empty */

    lua_close(L);
    return 0;
}

关于c++ - Lua C API - 使用同名的变量和函数加载多个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61683579/

相关文章:

apache - 如何从Web服务器(如Apache)中调用R?

embedded - 小型 RISC 仿真器

c++ - C 和 C++ 库错误

lua - 为什么我得到 "attempt to call global ' require'(零值)”?

c++ - 如何将 gabor 过滤器应用于 opencv 中的图像?

lua - 最新版本的Loadstring函数替换

variables - 在 Lua 中控制变量范围;它正在改变两个 Vars

perl - 如何在嵌入式 perl 解释器中动态加载 perl 扩展?

java - 服务器和线程模型

C++ 字节数组到 int