Lua中使用'require'但是文件只存在于内存中。

设置:我在C/C++环境中使用Lua。

我在磁盘上有几个Lua文件。这些文件被读入内存,一些更多的仅存储在内存中的Lua文件在运行时变得可用。比如,考虑一个编辑器,有额外的未保存的Lua文件。

因此,我在内存中有一个list<identifier, lua_file_content>。其中一些文件在内部有require语句。当我尝试将所有这些文件加载到Lua实例中(目前通过lua_dostring),我会得到attempt to call global require (a nil value)

是否有可能提供一个require函数,替换旧的函数,并只使用在内存中提供的文件(这些文件在C端上)?

是否有另一种允许这些文件中的require的方法,而不必在磁盘上有需要的文件?

例如,从仅存储在内存中而不进行修改地加载Lua stdlib(实际上这是我的测试用例)。

点赞
用户752976
用户752976

一个非常简单的 C++ 函数可以模仿 require,伪代码如下:

int my_require(lua_State* state) {
    // 获取模块名
    const char* name = lua_tostring(state);
    // 查找是否已经加载了该模块
    if (mymodules.find(name) != mymodules.end())
        luaL_loadbuffer(state, buffer, size, name);
    // chunk 现在在栈顶
    lua_call(state)
    return 1;
}

将此函数命名为 require 并暴露给 Lua 即可使用。

此外要注意,为了完全模仿 require 的行为,可能需要注意 package.loaded,以避免代码被加载两次。

2013-09-23 17:45:19
用户646619
用户646619

与其替换 require,为什么不向 package.loaders 添加一个函数呢?代码几乎相同。

int my_loader(lua_State* state) {
    // 获取模块名称
    const char* name = lua_tostring(state);
    // 查找是否已加载该模块
    if (mymodules.find(name) != mymodules.end())
    {
        luaL_loadbuffer(state, buffer, size, name);
        // chunk 现在在 stack 顶端
        return 1;
    }

    //未发现目标模块
    return 0;
}

// 在加载 lua 状态时,将此插入 package.loaders。

http://www.lua.org/manual/5.1/manual.html#pdf-package.loaders

2013-09-24 13:53:51
用户5126743
用户5126743

在 Lua 5.2 中,不存在 package.loaders,现在叫做 package.searchers

#include <stdio.h>
#include <string>
#include <lua.hpp>

std::string    module_script;

int MyLoader(lua_State *L)
{
    const char *name = luaL_checkstring(L, 1);  // 模块名

//  std::string    result = SearchScript(name); // 从数据库中搜索你的脚本。
    std::string    result = module_script;      // 只是一个演示。

    if( luaL_loadbuffer(L, result.c_str(), result.size(), name) )
    {
        printf("%s", lua_tostring(L, -1));
        lua_pop(L, 1);
    }

    return 1;
}

void SetLoader(lua_State* L)
{
    lua_register(L, "my_loader", MyLoader);

    std::string     str;

//  str += "table.insert(package.loaders,   2, my_loader) \n";   // 老于 lua v5.2
    str += "table.insert(package.searchers, 2, my_loader) \n";

    luaL_dostring(L, str.c_str());
}

void SetModule()
{
    std::string     str;

    str += "print([[It is add.lua]]) \n";
    str += "return { func = function() print([[message from add.lua]]) end } \n";

    module_script=str;
}

void LoadMainScript(lua_State* L)
{
    std::string     str;

    str += "dev = require [[add]] \n";
    str += "print([[It is main.lua]]) \n";
    str += "dev.func() \n";

    if ( luaL_loadbuffer(L, str.c_str(), str.size(), "main") )
    {
        printf("%s", lua_tostring(L, -1));
        lua_pop(L, 1);
        return;
    }
}

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

    luaL_openlibs(L);

    SetModule(L);       // 把模块写在内存中。Lua 没有加载它。
    SetLoader(L);
    LoadMainScript(L);

    lua_pcall(L,0,0,0);
    lua_close(L);

    return 0;
}
2016-04-18 12:00:38