2013-09-23 10 views
8

設定:私はC/C++環境からLuaを使用しています。Lua 'require'しかしファイルはメモリ内にのみあります

私はいくつかのluaファイルをディスクに持っています。これらはメモリに読み込まれ、実行時に利用できるようになるメモリのみのluaファイルが増えます。たとえば考える追加の保存されていないluaファイルと一緒にエディタを開きます。

私はlist<identifier, lua_file_content>を記憶しています。これらのファイルにはrequire文が含まれています。これらのファイルを(現在lua_dostringを介して)ルアインスタンスにロードしようとすると、私はattempt to call global require (a nil value)となります。

require機能を提供する可能性はありますか?古いものを置き換えて、提供されたメモリファイル(これらのファイルはC側にあります)を使用するだけですか?

ディスクに必要なファイルがなくても、これらのファイルにrequireを許可する別の方法はありますか?

たとえば、lua stdlibを変更せずにメモリからロードすることがあります。 (これは実際に私のテストケースである)

答えて

8

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

ありがとう、非常にうまく動作します。暗黙のうちにpackage.loadedを処理するので、より良い解決策と思われるので、私は受け入れられた解決策をこれに変更しました。 –

5

requireを模倣する非常に簡単C++の関数は次のようになります(擬似コード)

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

requireとしてのLuaにこの機能を公開し、あなたが行ってもいいです。

requireの動作を完全に模倣したいと思っている場合は、コードを2度読み込まないように、おそらくpackage.loadedを処理する必要があります。

+0

申し訳ありませんが、私はルアの専門家です。メモリからファイルをロードする前に、この関数に 'require'という名前を付けると思いますか? –

+0

あなたはそれを編集しました。 –

+0

ありがとう、とてもうまくいきます。 –

1

それは今package.searchersと呼ばLUA 5.2
にはpackage.loadersはありません。

#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; 
} 
関連する問題