Lua 'require' but files are only in memory

纵饮孤独 提交于 2021-01-21 04:08:58

问题


Setting: I'm using Lua from a C/C++ environment.

I have several lua files on disk. Those are read into memory and some more memory-only lua files become available during runtime. Think e.g. of an editor, with additional unsaved lua files.

So, I have a list<identifier, lua_file_content> in memory. Some of these files have require statements in them. When I try to load all these files to a lua instance (currently via lua_dostring) I get attempt to call global require (a nil value).

Is there a possibility to provide a require function, which replaces the old one and just uses the provided in memory files (those files are on the C side)?

Is there another way of allowing require in these files without having the required files on disk?

An example would be to load the lua stdlib from memory only without altering it. (This is actually my test case.)


回答1:


Instead of replacing require, why not add a function to package.loaders? The code is nearly the same.

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




回答2:


A pretty straightforward C++ function that would mimic require could be: (pseudocode)

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;
}

Expose this function to Lua as require and you're good to go.

I'd also like to add that to completely mimic require's behaviour, you'd probably need to take care of package.loaded, to avoid the code to be loaded twice.




回答3:


There is no package.loaders in lua 5.2
It called package.searchers now.

#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;
}


来源:https://stackoverflow.com/questions/18965489/lua-require-but-files-are-only-in-memory

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!