Lua's kompilierte Skripte sind so ziemlich der rohe Bytecode, der nach einem kurzen Header ausgegeben wurde. Der Header dokumentiert einige der Eigenschaften der Plattform, die zum Kompilieren des Bytecodes verwendet wurden, aber der Lader prüft nur, ob die aktuelle Plattform die gleichen Eigenschaften aufweist.
Leider verursacht dies Probleme beim Laden von Bytecode kompiliert auf einer anderen Plattform, auch wenn von der gleichen Version von Lua kompiliert. Natürlich können Skripts, die von verschiedenen Versionen von Lua kompiliert wurden, nicht funktionieren, und da die Versionsnummer von Lua im Bytecode-Header enthalten ist, wird der Versuch, sie zu laden, vom Kern erfasst.
Die einfache Antwort ist, Skripte nur nicht zu kompilieren. Wenn Lua das Skript selbst kompiliert, müssen Sie sich nur über mögliche Versionsunterschiede zwischen Lua-Kernen in Ihren verschiedenen Builds Ihrer Anwendung Gedanken machen, und das ist nicht schwer zu bewältigen.
Tatsächlich unterstützt eine vollständige Kreuzkompatibilität für kompilierten Bytecode not easy. In dieser E-Mail, identifiziert Mike Pall die folgenden Probleme:
Endianess: swap auf Ausgabe nach Bedarf.
sizeof(size_t)
, wirkt sich riesige String-Konstanten: für Überlauf überprüfen, wenn Herabstufung.
sizeof(int)
, wirkt MAXARG_Bx
und MAXARG_sBx
: für Überlauf überprüfen, wenn Herabstufung.
: einfach in C, aber nur wenn der Host und das Ziel demselben FP-Standard folgen; Präzision Verlust beim Upgrade (seltener Fall); warnen vor nicht ganzzahligen Zahlen, wenn zu int32
herabstufen.
Von all den Diskussionen, die ich zu diesem Thema auf der Mailing-Liste gesehen habe, sehe ich zwei wahrscheinlich tragfähige Ansätze, vorausgesetzt, dass Sie nicht bereit sind, nur zu prüfen, die nicht kompilieren Lua-Skripten Versand.
Die erste wäre, die Byte-Reihenfolge zu beheben, wenn die kompilierten Skripte geladen werden. Dies stellt sich als einfacher heraus, als Sie es erwarten würden, da dies durch Ersetzen der Low-Level-Funktion, die die Skriptdatei liest, ohne erneute Kompilierung des Kerns erfolgen kann. In der Tat kann es sogar in reinem Lua getan werden, indem Sie Ihre eigene chunk reader Funktion zu lua_load() zur Verfügung stellen. Dies sollte funktionieren, solange das einzige Kompatibilitätsproblem auf Ihren Plattformen die Bytereihenfolge ist.
Die zweite besteht darin, den Kern selbst zu patchen, um eine gemeinsame Darstellung für kompilierte Skripte auf allen Plattformen zu verwenden. Dies wurde als möglich durch Luiz Henrique de Figueiredo beschrieben:
.... Ich bin überzeugt, dass der beste Weg zur Byte-Reihenfolge oder Cross-Compilierung Dritter dump/undump Paare ist. Die Dateien ldump.c und lundump.c sind vollständig austauschbar; Sie exportieren einen einzelnen, wohldefinierten Einstiegspunkt . Das Format von vorkompilierten Brocken ist nicht heilig, überhaupt heilig; Sie können jedes Format verwenden, solange ldump.c und lundump.c darüber einig sind . (Zum Beispiel Rici Lake ist erwägen ein Textformat für vorkompilierte Stücke zu schreiben.) ....
Persönlich würde ich ernsthaft in Erwägung empfehlen, nicht zu geben, um die Skripte vorzunehmen Kompilieren und somit vermeiden die Plattform Portabilitätsprobleme vollständig.
Bearbeiten: Ich habe meine Beschreibung des Bytecode-Headers dank LHF Kommentar aktualisiert. Ich hatte diesen Teil der Lua-Quelle noch nicht gelesen, und ich hätte es wahrscheinlich überprüfen sollen, bevor ich ziemlich durchsetzungsfähig darüber bin, welche Informationen in der Kopfzeile vorhanden sind oder nicht.
Hier ist das Fragment von lundump.c
, das eine Kopie der Kopfzeile bildet, die mit der laufenden Plattform für den Vergleich mit dem Bytecode übereinstimmt, der geladen wird. Es wird einfach mit memcmp()
für eine genaue Übereinstimmung mit dem Header aus der Datei verglichen, so dass jede Nichtübereinstimmung dazu führt, dass der Bestandslader (luaU_undump()
) die Datei zurückweist.
/*
* make header
*/
void luaU_header (char* h)
{
int x=1;
memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
h+=sizeof(LUA_SIGNATURE)-1;
*h++=(char)LUAC_VERSION;
*h++=(char)LUAC_FORMAT;
*h++=(char)*(char*)&x; /* endianness */
*h++=(char)sizeof(int);
*h++=(char)sizeof(size_t);
*h++=(char)sizeof(Instruction);
*h++=(char)sizeof(lua_Number);
*h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
}
Wie zu sehen ist, wird der Header 12 Byte lang und enthält eine Signatur (4 Byte, "<esc>Lua
"), Version und Format-Codes, ein Flag-Byte für Byte-Reihenfolge, Größen der Typen int
, size_t
, Instruction
und lua_Number
, und ein Flag, das anzeigt, ob lua_Number
ein integraler Typ ist.
Dadurch können die meisten Plattformunterscheidungen abgefangen werden, es wird jedoch nicht versucht, auf jede Art und Weise zu unterscheiden, in der sich Plattformen unterscheiden können.
Ich stehe immer noch zu den oben gemachten Empfehlungen: Erstens, kompilierbare Quellen; Oder passen Sie ldump.c
und lundump.c
an, um ein allgemeines Format zu speichern und zu laden, mit der zusätzlichen Anmerkung, dass jedes benutzerdefinierte Format das LUAC_FORMAT-Byte des Headers neu definieren sollte, um nicht mit dem Bytecode-Format zu verwechseln.
Weitere Informationen benötigt: irgendwelche Fehlermeldungen bei diesem Fehler zu laden? –