2013-09-23 8 views
8

Ustawienie: Używam Lua ze środowiska C/C++.Lua "wymagają", ale pliki są tylko w pamięci

Mam kilka plików lua na dysku. Są one odczytywane do pamięci, a niektóre pliki pamięci Lua dostępne tylko w pamięci stają się dostępne w czasie wykonywania. Pomyśl np. edytora, z dodatkowymi niezapisanymi plikami lua.

Tak, mam w pamięci list<identifier, lua_file_content>. Niektóre z tych plików zawierają w sobie instrukcje require. Kiedy próbuję załadować wszystkie te pliki do instancji lua (obecnie przez lua_dostring) otrzymuję attempt to call global require (a nil value).

Czy istnieje możliwość udostępnienia funkcji require, która zastępuje starą i używa tylko plików znajdujących się w pamięci (te pliki znajdują się po stronie C)?

Czy istnieje inny sposób zezwalania na require w tych plikach bez posiadania wymaganych plików na dysku?

Przykładem może być załadowanie lua stdlib z pamięci tylko bez zmiany jej. (Jest to rzeczywiście mój przypadek testowy).

Odpowiedz

8

Zamiast wymieniać require, czemu nie dodać funkcji do package.loaders? Kod jest prawie taki sam.

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

Dziękuję bardzo, działa również bardzo dobrze. Ponieważ wydaje się, że jest to lepsze rozwiązanie, ponieważ obsługuje pakiet.zainstalowany implicitely, zmieniłem zaakceptowane rozwiązanie na to. –

5

A całkiem proste C funkcja ++, które naśladować require mogą być: (pseudokod)

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

wystawiać funkcji Lua jako require i jesteś dobry, aby przejść.

Chciałbym dodać, że aby całkowicie naśladować zachowanie require, prawdopodobnie trzeba będzie zająć się package.loaded, aby uniknąć dwukrotnego ładowania kodu.

+0

Przepraszam, nie jestem ekspertem od Lua. Przypuszczam, że zapewniam tę funkcję z nazwą 'require' na instancję lua przed załadowaniem plików z pamięci? –

+0

OK, edytujesz, odebrałeś odpowiedź. –

+0

Dziękuję bardzo, działa bardzo dobrze. –

1

Nie ma package.loaders w Lua 5,2
Nazywa package.searchers teraz.

#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; 
} 
Powiązane problemy