Aktuelle Zeit: 10.08.2020 10:11

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 8 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: LUA - Script in PB-Programmen
BeitragVerfasst: 02.01.2017 18:01 
Offline

Registriert: 29.08.2004 13:18
Ich hab die C-Headers für PB übersetzt und auch ein paar Beispiele geschrieben:
http://game.gpihome.eu/PureBasic/lua/

Wozu braucht man LUA?
Lua ist wie gesagt eine Scriptsprache. World of Warcraft nutzt diese bspw. um die Addonschnittstelle zu realisieren. Wenn man teile des Programmcodes in LUA realisiert oder "Hook"-Schnittstellen schafft, kann so jeder ein Spiel/Programm in verhalten verändern und erweitern. Eine andere Anwendungsmöglichkeit wären bspw. Konfigurationsdateien, die auch Rechnungen und Bedingungen enthalten können. Gibt sicherlich viele Anwendungsmöglichkeiten. Man stelle sich vor, man könnte den PureBasic-Compiler sagen: alles was zwischen den Codewörtern "Class" und "EndClass" steht soll erstmal an ein LUA-Script weitergegeben werden....
Zudem ist LUA für fast alle Plattformen erhältlich - naja in der Theorie, dazu später mehr :)

Bitte beachten, vollständig getestet ist das ganze nicht, ein Fehler kann immer irgendwo sein!
Ich hab auch gleich einen unschönen Bug in PureBasic gefunden:
Wenn man PrototypeC mit Quads verwendet:
PrototypeC.q function()
wird nur ein 16Bit-Wert zurückgegeben, der rest wird verworfen. Bei 64Bit ist das noch kein Problem, hier nimmt man einfach Integer (ist ja gleich groß), da gehts. Bei 32Bit ist das ganze nicht so schön.

Die Routinen sind für Windows geschrieben und von der LUA.DLL liegt auch eine 32Bit und 64Bit Version vor. Für Linux liegt eine 64Bit-Bibliothek in so-Format vor, aber da ich kein Linux habe, komplett ungetestet! Für Macs hab ich überhaupt nichts gefunden. Gedownloaded wurden die DLL/SO von http://luabinaries.sourceforge.net/index.html

In Example-Ordner gibt es ein paar Beispiele:
Example1:
Einfaches Beispiel wie man eine Lua-Datei aus den Datenblock lädt und aufruft. Und wie man eine Funktion aus den LUA-Script nachträglich ausführt.

Example2:
Wie man mit Metatabellen schreibt und so eine eigene Bibliothek schreibt und mit Userdata eigene Daten in LUA einspeisen kann.

Example3:
Leider ist es etwas Trickreich, wenn man die Standard-Bibliotheken von LUA sperren will. Gerade die io und os Bibliothek ermöglichen den Zugriff auf jede Datei auf den Rechner. Das kann ungewünscht sein, bspw. wenn man die LUA-Scripte zwingen will, in einem bestimmten Verzeichnis Daten abzulegen. Die Methode lässt sich auch durch ein "os = require('os')" in LUA-Script nicht mehr aushebeln. Alternativ müsste man LUA selbst compilen und die Bibliotheken kürzen. Da ich aber zukünftig einfach eine Binary downloaden will, ist mir die Methode lieber :)
Zudem werden hier drei Lua-Scripte in die gleiche VM geladen und ausgeführt, dabei werden die Script-Adressen zum ausführen in einer LUA-Tabelle gespeichert - eine bessere Methode gibts in Example5. Ich hab die Methode nur mal drin gelassen, falls jemand mal mit Tabellen handtieren will.

Example4:
Lädt eine LUA-Datei und speichert diese dann in binär-form ab. Anschließend wird in einer neuen VM die binärdatei eingelesen und ausgeführt. LUA benutzt (wie java) einen Pseudobinärcode. Durch diese Methode erreicht man zweierlei: Erstes muss der Quellcode nicht mehr compiled werden und zweitens er ist nicht mehr so leicht änderbar.

Example5:
Lädt mehrere LUA-Scripte in eine "VM" und führt diese aus. Zu beachten ist, das jedes Script in einen Chunk geladen wird und man nur einen Chunk einzeln starten kann. Die Adressen des Chunks (in Prinzip ist das wie eine Adresse einer Funktion) wird dabei in der #LUA_REGISTRYINDEX hinterlegt. Das Problem bei der Kommunikation mit LUA ist, das es Datenformate in LUA gibt, die es so nicht in PB gibt. Bspw eine Adresse zu einer LUA-Funktion. Man kann aber diese Adresse in der #LUA_REGISTRYINDEX speichern (hat nichts mit der Windows-Registry zu tun!) und bekommt einen Handle zurück - ähnlich wie bei Purebasic mit #pb_any. Das kann man dann verwenden und in PB speichern.

Example6:
Eine simple grafische Demo. Ich hab die Beispielbilder von PB genommen, so das ich keine reinkopieren brauchte :) Kann man sicher noch ausbauen, bspw. das LUA-Script in einen eigenen Task endlos laufen lassen.

In der Zip sind zwei pbi:
module_lua.pbi

diese muss man einfach einbinden und mit UseModule "anmelden" und mittels lua_initalize() starten:
Code:
XIncludeFile "module_lua.pbi"
UseModule lua
If Lua_Initialize()=#False
  End
EndIf
....
Lua_Dispose()


lua_initalize() lädt dann die DLL und initaliziert sämtliche Funktionen, dispose entlädt LUA.dll. Der Aufruf ist nötig, damit man auch in einer DLL LUA nutzen kann.

module_lua_extern.pbi

die module_lua_extern.pbi ist ein kleiner Trick, der mir sehr viel Schreibarbeit abnimmt. Die DLL wird mittels Prototypen in PureBasic eingebunden. Der Nachteil ist, das man die Prototypen und Global - deklarationen in DeclareModule unterbringen muss, aber die Zuweisung in Module-Block. Zudem wollte ich das bei lua_dispose() die ganzen funktionen auf die Adresse 0 verweisen und nicht irgendwo in Speicher, wo die DLL war. Lieber ein sauberer Absturz, als wenn willkürlich eine Funktion versehentlich aufgerufen wird. In schlimmsten Fall funktioniert das ganze sogar noch...

So, mehr fällt mir jetzt gerade nicht ein :) Sorry fürs etwas wirr schreiben, bei Fragen einfach fragen.

Hier noch ein paar Links zum einlesen:
https://www.lua.org/
http://www.fh-wedel.de/~si/seminare/ws0 ... a/lua0.htm

_________________
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: LUA - Script in PB-Programmen
BeitragVerfasst: 03.01.2017 13:08 
Offline
Benutzeravatar

Registriert: 10.09.2004 09:59
Wenn ich das gewusst hätte...
Bin selbst seit ein paar Tagen an LUA, allerdings weniger intensiv, als ich das gerne gehabt hätte.

Das kommt jetzt echt gut, lieber meine halben Sachen wegwerfen, als weiter kämpfen.

Vielen Dank!!

_________________
Link tot?
Ändere h3x0r.ath.cx in hex0rs.coderbu.de und alles wird gut.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: LUA - Script in PB-Programmen
BeitragVerfasst: 03.01.2017 14:23 
Offline

Registriert: 29.08.2004 13:18
ich hab auch erst vor ein paar Tagen begonnen. Anscheinend gabs mal eine Userlibrary und ich hab eine alte (und lücken und fehlerhafte) Include-Datei gefunden :)

Du hattest aber Glück, eigentlich wollte ich Ruby umsetzen, aber da ist die Dokumentation irgendwie schlechter. Ich hab auch nicht so eine einfache dll-Datei für Windows gefunden.

_________________
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: LUA - Script in PB-Programmen
BeitragVerfasst: 03.01.2017 15:31 
Offline
Benutzeravatar

Registriert: 08.03.2013 14:27
Wohnort: ERB
Danke für die Mühe.

Ich würde mich eher für ein ECMAScript Interpreter interessieren. Nur leider lassen sich die nur schwer einbinden, da sie meistens in C++ geschrieben sind oder als Lib erst kompilliert werden müssen.

Aber bis dahin hilft das hier auch :)

_________________
USAC Protokoll
Universal Stringbased Application Communication Protocoll

Github: Zum Spezifikationdokument v0.01


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: LUA - Script in PB-Programmen
BeitragVerfasst: 04.01.2017 00:53 
Offline
Benutzeravatar

Registriert: 10.09.2004 09:59
So, das lässt sich schonmal gut an.
Deine Macro Technik ist übrigens... ähm, sagen wir: :freak:

Aber egal.
Was mich jetzt doch etwas Arbeit gekostet hat:
Strings in LUA dürfen auch Chr(0) beinhalten.
Kommt vermutlich eh nie vor?
Naja, in meinem Fall schon, diese Tatsache hat nämlich einen ganz tollen Nebeneffekt:
Man kann Memorypuffer von/zu LUA als Strings schicken.

Naja, jedenfalls ist das so wie es im Moment ist etwas doof, weil PB ja bekanntlich Strings nach Chr(0) einfach abschneidet.

Daher habe ich folgende Erweiterungen hinzugefügt (alles in module_lua.pbi):
In DeclareModule:
Code:
PrototypeC.i lua_pushBuffer(lua_State.i, *Buffer, Size.i)
Global lua_pushBuffer.lua_pushBuffer
Declare lua_tobuffer(state, i, *Size.INTEGER = 0)

(mit dem Macro-Irrsinn geht das vermutlich nicht ohne Hand anzulegen, schliesslich wird dieser Prototyp als Kopie an lua_pushlstring geheftet)
im Module:
Code:
Procedure.i lua_tobuffer(state, i, *Size.INTEGER = 0)
   Protected *str = lua_tolstring(state, i, #Null)
   If *Size
      *Size\i = lua_rawlen(state, i)
   EndIf
   ProcedureReturn *str
EndProcedure

und unter "UndefineMacro c34"
Code:
lua_pushBuffer = GetFunction(DLL_LUA, "lua_pushlstring")


Man muss den Pointer, der von lua_tobuffer zurückkommt, allerdings zur weiteren Verwendung in einen eigenen Memorybereich kopieren.
Weil der nicht ewig gültig ist.

Eins ist mir auch aufgefallen, da bin ich noch nicht dahinter gekommen:
Ohne UseModule funktioniert es nicht zuverlässig, da kommen wirre Fehlermeldungen (Macro nicht definiert, und so was).

_________________
Link tot?
Ändere h3x0r.ath.cx in hex0rs.coderbu.de und alles wird gut.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: LUA - Script in PB-Programmen
BeitragVerfasst: 04.01.2017 01:36 
Offline

Registriert: 29.08.2004 13:18
Ja null ist da ein reguläres Zeichen - und verursacht eine Fehlermeldung, wenn man ihn in lua-code hat!

die ganzen Macros (bis auf die Extern) sind 1:1 aus den c-Header übernommen. Die erleichtern viele Aufrufe. Die ganzen macros beachten nicht, das sie in Modulen sind, deshalb geht ohne usemodule sehr wenig. Wobei das von mir durchaus gewollt ist, weil die API für C genauso designed ist und eben keine API für C++ ist. Ich wollte, das man die ganzen C-Beispiele nahezu 1:1 übernehmen kann. sonst würdest du lua::pushlstring schreiben. In ein Modul habe ich das ganze nur gepackt, damit man es auch von einen Modul aus aufrufen kann. Es gibt ja kein "shared" für Module.

dein lua_pushbuffer ist doch identisch mit lua_pushlstring?
ich würde das mittels Macro lösen
Code:
Macro lua_pushBuffer(state,buffer,size):lua_pushlstring(state,buffer,size):endmacro


dein lua_toBuffer() ist auch etwas umständlicher als nötig:
die Funktion ist so in C deklariert:
const char *lua_tolstring (lua_State *L, int index, size_t *len); - https://www.lua.org/manual/5.3/manual.h ... _tolstring
du musst als die Länge nicht mit rawlen auslesen, sondern als dritten Parameter einfach die Adresse zu einer Integervariable übergeben.

damit würde ein einfaches Macro reichen:
Code:
macro lua_tobuffer(a,b,c=0):lua_tolstring(a,b,c):endmacro


Einfach beide vor EndDeclareModul einfügen.

das mit "Extern" und Includefile spart mir ein haufen arbeit. Man kann in den Macro extern() sehen, was grob gemacht wird.
extern (lua_copy , (lua_State.i, fromidx.i, toidx.i) )
erster Parameter ist hier die Funktion aus der DLL und zeitgleich der Name. der zweite paramater ist die Parameterteil
beim ersten include wird der Prototyp und die globale "variable" erstellt:
Code:
; extern (lua_copy   ,(lua_State.i, fromidx.i, toidx.i))
PrototypeC.i __proto_lua_copy (lua_State.i, fromidx.i, toidx.i)
Global lua_copy.__proto_lua_copy

beim zweiten wird die Function aus der DLL geklaubt
Code:
; extern (lua_copy   ,(lua_State.i, fromidx.i, toidx.i))
lua_copy = GetFunction(DLL_LUA, "lua_copy")

und beim dritten mal (die DLL wurde entladen und ich setzt hier alle funktionen auf 0. falls man jetzt versehentlich eine function aufruft, schmiert das Programm sauber ab und macht nicht irgendwas jetzt zufällig an der Position der DLL gelandet ist)
Code:
; extern (lua_copy   ,(lua_State.i, fromidx.i, toidx.i))
lua_copy = 0


Ich muss also nur noch an einer Stelle das ganze bearbeiten - wie es auch in C geht. PB ist da leider etwas umständlich geraten.

Edit: Was ganz wichtiges vergessen:
lua macht von den Buffer immer eine Kopie! und selbiges sollte man auch immer selber machen, der buffer von lua_tolstring wird von lua verwaltet und gnadenlos irgendwann freigeben. Er wurde nur für den C-Aufruf erstellt und kann somit schon beim nächsten API-Aufruf zerstört werden!

_________________
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: LUA - Script in PB-Programmen
BeitragVerfasst: 04.01.2017 11:57 
Offline
Benutzeravatar

Registriert: 10.09.2004 09:59
GPI hat geschrieben:
dein lua_pushbuffer ist doch identisch mit lua_pushlstring?
ich würde das mittels Macro lösen

Jein, man beachte den anders deklarierten Prototype.
Mit Deinem Makro bekomme ich immernoch eine Compilerwarnung, wenn ich einen Puffer an lua_pushlstring übergebe.

Ich wollte die ursprüngliche Funktion beibehalten, weil es ja in aller Regel funktioniert, wer hat schon chr(0) in einem String...

Zitat:
das mit "Extern" und Includefile spart mir ein haufen arbeit.

War mir schon klar, aber übersichtlich ist anders.
Und ehrlich gesagt habe ich nur 10 Minuten gebraucht, um den Code entsprechend umzuändern, also ohne die extern-Makros.
Das macht man ja nicht per Hand, sondern per Regex.


Das mit dem lua_toBuffer() ist allerdings richtig, das ist natürlich wesentlich einfacher!

_________________
Link tot?
Ändere h3x0r.ath.cx in hex0rs.coderbu.de und alles wird gut.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: LUA - Script in PB-Programmen
BeitragVerfasst: 04.01.2017 12:08 
Offline

Registriert: 29.08.2004 13:18
damit wäre es vermutlich schneller gegangen:
viewtopic.php?f=8&t=29152&hilit=preprocess
Das Tool löst alle macros vollständig auf. allerdings sind dann auch die ganzen hilfsmacros weg, die sollte man wieder einfügen. Aber um den Teil bei include rauszuklauben gehts schneller.

Übersichtlich ist so eine Sache. Ich finde es erhöht die übersichtlichkeit enorm. Vorallen ist es leichter zu pflegen. Wenn jetzt 5.3.4 kommt, muss ich neue Funktionen nur einmal an einer stelle (in der extern.pbi) einfügen und das wars dann. Genauso wenn ich fehler find. Ansonsten müsste ich immer an drei Stellen suchen, nicht so ideal.

_________________
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 8 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste


Sie dürfen keine neuen Themen in diesem Forum erstellen.
Sie dürfen keine Antworten zu Themen in diesem Forum erstellen.
Sie dürfen Ihre Beiträge in diesem Forum nicht ändern.
Sie dürfen Ihre Beiträge in diesem Forum nicht löschen.

Suche nach:
Gehe zu:  

 


Powered by phpBB © 2008 phpBB Group | Deutsche Übersetzung durch phpBB.de
subSilver+ theme by Canver Software, sponsor Sanal Modifiye