Frage

Ich arbeite an einem kleinen Projekt versucht lua mit c zu integrieren ++. Mein Problem ist jedoch wie folgt:

ich mehrere Lua-Skripte haben, lässt sie rufen s1.lua s2.lua und s3.lua. Jeder von ihnen hat die folgenden Funktionen: setVars () und executeResults ()

.

Jetzt bin ich in der Lage eine lua-Datei über LuaL_dofile zu rufen und sofort nach Gebrauch setVars () und / oder executeResults (). Das Problem hierbei ist jedoch, dass, nachdem ich Lese s2.lua kann ich nicht mehr die Funktionen von s1.lua nennen. Dies würde bedeuten, ich habe die LuaL_dofile auf s1.lua Redo Zugriff auf die Funktion wieder zu erlangen und tun, damit ich verlieren Zugriff auf die Funktionen in s2.lua.

Gibt es eine Möglichkeit, alle lua Dateien in einer Reihe einfach zu laden, und danach zu beginnen, ihre Funktionen nach Belieben aufrufen? So etwas wie S1-> executeResults () S5-> executeResults () S3-> setVars () etc.

Im Moment habe ich bereits ein System eingerichtet, mit boost :: filesystem alle lua Dateien in einem Ordner zu erkennen, ich dann speichern Sie diese Dateinamen in einem Vektor und dann einfach Iterierte über den Vektor jede lua-Datei in einer Reihe zu laden.

Der Verzicht auf die Füllung des Vektors mit lua Dateinamen meiner Plugin Ladefunktion wie folgt aussieht im Moment:

void Lua_plugin::load_Plugins(){
 std::vector<std::string>::const_iterator it;
 for (it=Lua_PluginList.begin(); it!=Lua_PluginList.end(); it++){
  std::cout<<"File loading: " << *it << std::endl;
  std::string filename =  *it;
  std::string filepath = scriptdir+filename;
  if (luaL_loadfile(L, filepath.c_str()) || lua_pcall(L, 0, 0, 0)) {
   std::cout << "ScriptEngine: error loading script. Error returned was: " << lua_tostring(L, -1) << std::endl;
  }
 }
}

Um es ein bisschen mehr klar, alles, was ich in der .lua die haben, ist so etwas wie folgt aus:

-- s1.lua

setVars()
--do stuff
end

executeResults()
--dostuff
end

etc, aber ich würde auf den Ruf s1.lua können, wie setVars () und s2.lua der setVars () nach einfach beide in einer Reihe geladen zu haben.

War es hilfreich?

Lösung

Dies ist effektiv, was gwell vorgeschlagen, um den C-API:

#include <stdio.h>

#include "lua.h"

static void
executescript(lua_State *L, const char *filename, const char *function)
{
    /* retrieve the environment from the resgistry */
    lua_getfield(L, LUA_REGISTRYINDEX, filename);

    /* get the desired function from the environment */
    lua_getfield(L, -1, function);

    return lua_call(L, 0, 0);
}

static void
loadscript(lua_State *L, const char *filename)
{
    /* load the lua script into memory */
    luaL_loadfile(L, filename);

    /* create a new function environment and store it in the registry */
    lua_createtable(L, 0, 1);
    lua_getglobal(L, "print");
    lua_setfield(L, -2, "print");
    lua_pushvalue(L, -1);
    lua_setfield(L, LUA_REGISTRYINDEX, filename);

    /* set the environment for the loaded script and execute it */
    lua_setfenv(L, -2);
    lua_call(L, 0, 0);

    /* run the script initialization function */
    executescript(L, filename, "init");
}

int
main(int argc, char *argv[])
{
    lua_State *L;
    int env1, env2;

    L = (lua_State *) luaL_newstate();
    luaL_openlibs(L);

    loadscript(L, "test1.lua");
    loadscript(L, "test2.lua");

    executescript(L, "test1.lua", "run");
    executescript(L, "test2.lua", "run");
    executescript(L, "test2.lua", "run");
    executescript(L, "test1.lua", "run");

    return 0;
}

Testskripte:

-- test1.lua
function init() output = 'test1' end
function run() print(output) end

-- test2.lua
function init() output = 'test2' end
function run() print(output) end

Ausgabe:

test1
test2
test2
test1

weggelassen ich alle Fehler der Kürze der Handhabung, aber Sie werden den Rückgabewert von luaL_loadfile und Verwendung lua_pcall statt lua_call überprüfen möchten.

Andere Tipps

Die setfenv() Funktion kann verwendet werden, geladen, um eine Sandbox oder Umgebung für jede Datei zu erstellen.

Dieses Beispiel zeigt, dass alle drei Dateien mit widersprüchlichen Funktionen geladen werden können und dass die Funktionen können in beliebiger Reihenfolge aufgerufen werden. Ähnlicher Code könnte in C ++ geschrieben werden. In diesem Beispiel wird nur die Druckfunktion für jede Umgebung, könnte mehr in Ihrem Szenario benötigt werden.

function newEnv()
  -- creates a simple environment
  return {["print"]=print}
end

local e={} -- environment table
local c    -- chunk variable

-- first instance
c = loadstring([[function f() print("1") end]])
e[#e+1] = newEnv()
setfenv(c, e[#e]) -- set the loaded chunk's environment
pcall(c) -- process the chunk (places the function into the enviroment)

-- second instance
c = loadstring([[function f() print("2") end]])
e[#e+1] = newEnv()
setfenv(c, e[#e])
pcall(c)

-- third instance
c = loadstring([[function f() print("3") end]])
e[#e+1] = newEnv()
setfenv(c, e[#e])
pcall(c)

pcall(e[3].f) --> 3
pcall(e[2].f) --> 2
pcall(e[1].f) --> 1
pcall(e[1].f) --> 1
pcall(e[2].f) --> 2
pcall(e[3].f) --> 3

Sie könnten einen neuen Zustand lua_newstate() für jede Datei erstellen. Dies wäre einfacher als meine vorherige Antwort. Es kann jedoch eine Leistungseinbuße haben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top