9

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

4

3 回答 3

11

而不是替换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

于 2013-09-24T13:53:51.473 回答
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 asrequire就可以了。

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

于 2013-09-23T17:45:19.910 回答
3

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;
}
于 2016-04-18T12:00:38.013 回答