Lua'require'但文件只在内存中

时间:2013-09-23 17:38:26

标签: lua

设置:我在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而不改变它。 (这实际上是我的测试用例。)

3 个答案:

答案 0 :(得分:9)

为什么不向require添加功能,而不是替换package.loaders?代码几乎相同。

int my_loader(lua_State* state) {
    // get the module name
    const char* name = lua_tostring(state);
    // find if you have such module loaded
    if (mymodules.find(name) != mymodules.end())
    {
        luaL_loadbuffer(state, buffer, size, name);
        // the chunk is now at the top of the stack
        return 1;
    }

    // didn't find anything
    return 0;
}

// When you load the lua state, insert this into package.loaders

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

答案 1 :(得分:5)

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

int my_require(lua_State* state) {
    // get the module name
    const char* name = lua_tostring(state);
    // find if you have such module loaded
    if (mymodules.find(name) != mymodules.end())
        luaL_loadbuffer(state, buffer, size, name);
    // the chunk is now at the top of the stack
    lua_call(state)
    return 1;
}

将此功能公开为Lua require,你很高兴。

我还想补充一点,以完全模仿require的行为,你可能需要处理package.loaded,以避免代码被加载两次。

答案 2 :(得分:2)

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);  // Module name

//  std::string    result = SearchScript(name); // Search your database.
    std::string    result = module_script;      // Just for demo.

    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";   // Older than 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);       // Write down module in memory. Lua not load it yet.
    SetLoader(L);
    LoadMainScript(L);

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

    return 0;
}