2013-09-23 9 views
8

Impostazione: sto usando Lua da un ambiente C/C++.Lua 'richiede' ma i file sono solo in memoria

Ho diversi file lua su disco. Questi vengono letti in memoria e alcuni file lua solo in memoria diventano disponibili durante il runtime. Pensa ad es. di un editor, con ulteriori file lua non salvati.

Quindi, ho un list<identifier, lua_file_content> nella memoria. Alcuni di questi file contengono le dichiarazioni require. Quando provo a caricare tutti questi file su un'istanza lua (attualmente tramite lua_dostring) ottengo attempt to call global require (a nil value).

Esiste la possibilità di fornire una funzione require, che sostituisce quella precedente e utilizza solo i file di memoria forniti (quei file sono sul lato C)?

C'è un altro modo di consentire require in questi file senza avere i file richiesti sul disco?

Un esempio potrebbe essere quello di caricare il lua stdlib dalla memoria solo senza alterarlo. (Questo è in realtà il mio banco di prova.)

risposta

8

Invece di sostituire require, perché non aggiungere una funzione a package.loaders? Il codice è quasi lo stesso.

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

La ringrazio molto, funziona anche molto bene. Dal momento che sembra essere la soluzione migliore, poiché gestisce il pacchetto. Caricato implicitamente, ho cambiato la soluzione accettata a questo. –

5

Un piuttosto semplice funzione C++ che imitano require potrebbe essere: (pseudo)

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

esporre questa funzione per Lua come require e siete a posto.

Vorrei anche aggiungere che per simulare completamente il comportamento di require, probabilmente dovresti aver cura di package.loaded, per evitare che il codice venga caricato due volte.

+0

Siamo spiacenti, non sono un esperto Lua. Direi di fornire questa funzione con il nome 'require' all'istanza di lua prima di caricare i file dalla memoria? –

+0

Ok, la modifica è stata risolta. –

+0

Grazie mille, funziona molto bene. –

1

Non c'è package.loaders in Lua 5.2
si chiama package.searchers ora.

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