Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Sa Jul 19, 2025 20:12

Foren-Übersicht » Sonstiges » Meinungen zu den Projekten
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Dynamic Pascal
BeitragVerfasst: Sa Mai 01, 2004 21:36 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Dez 13, 2002 12:18
Beiträge: 1063
Das Projekt klingt ja wieder sehr interessant - leider kann ich es zur Zeit nicht testen, da ich übers Wochenende kein Delphi zur Verfügung habe - werde mir das Ganze aber auf jeden Fall genauer ansehen - insbesondere als ich auch von fxPascal höchst begeistert bin.
Hast du vor, mit dem Projekt irgendwann auch "eigenständige" Programme schreiben zu können (also mit Einsprungpunkt in eine "Main" Routine), oder dient es "nur" der Integration geskripteter Klassen in bereits bestehende Anwendungen? (Wobei es natürlich auch im zweiteren Fall möglich sein sollte, selbst eine "Applikationsklasse" zu schreiben, deren "Main" Methode dann halt automatisch aufgerufen wird).

Was mich an der Umsetzung noch interessieren würde:
* wie schauts denn Unterstützung von Zeigern aus?
* werden auch dynamische Arrays unterstützt?
* welche Debugmöglichkeiten hast du für Skripts vorgesehen?

_________________
Viel Spaß beim Programmieren,
Mars
http://www.basegraph.com/


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 01, 2004 22:28 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Dynamic Pascal ist nur für die schnelle Ausführung von Scripts gedacht. Ich bin mir auch gar nicht sicher, ob man so umstellen kann, daß die units gespeichert werden. Ich habe erst überlegt direkt eine EXE/DLL erstellen zu lassen, aber dann hat man nicht mehr direkte Integration in Delphi und kann gleich eine DLL mit Delphi erstellen. Es kommt ja darauf an mit minimalem Aufwand die Anwendung flexibel machen zu können. Ich benötige das ganz konkret um Entities und Menüs zu scripten ohne immer noch auf eine Zwischenschicht Rücksicht zu nehmen. Und selbst bei einer DLL hat man eine Schnittstelle. Hierbei kann man einfach die Unit laden und muß die Klassen dann eben über FindClass suchen. Für den normalen Quelltext macht es überhaupt keinen Unterschied, ob die Klassen jetzt dynamisch nachgeladen wurden oder nicht. Ich habe mehrere Scriptmöglichkeiten ausprobiert, aber es läuft immer darauf hinaus, daß es eine Schnittstelle gibt. Das Problem ist aber, daß man die Schnittstelle zwischen Scripts und richtigem Code gar nicht immer im Vorraus definieren kann. Die Austauschbarkeit der Klassen ist hierbei Dynamic Pascal der große Nutzen. Man kann faktisch jede beliebige von TPersistent abgeleitete Klasse nachträglich durch eine gescriptete ersetzen ohne schon beim Erstellen der Klasse sich darüber Gedanken machen zu müssen. Wenn man sich die DLL's zu Quake und HL ansieht, dann sind das Spiel und das Mod letztendlich zwei verschiedene Programme. Und für alle Daten die in beiden Teilen benötigt werden, muß eine Schnittstelle definiert werden. Und es ist ungünstig Elemente die auf unterster Ebene ablaufen wie z.B. Zeichenoperation als Interface nach außen zu führen. Dann bekommt man eine seltsame Liste von Funktionen die gar nicht zusammengehören und im restlichen Programm teilweise auch gar nicht gleichzeit sichtbar sind. Bei Unreal ist das besser, aber es müssen spezielle Header erzeugt werden um die C++ Klassen mit den Scripten zu verbinden. Daher denke ich, daß dies die eleganteste Möglichkeit ist. Im CPU Fenster kann man sehen, daß direkt in die Routine gesprungen wird. Zeiger gibt es nicht, da man nicht verantworten kann, daß aus dem Internet geladener Code Zeigerberechnungen durchführt. Wenn man einen Type mit Referenzsemantik benötigt, kann man die Klassentypen und Klassenreferenzen benutzen. Lange Strings und dynamische Arrays habe ich bislang noch nicht eingebaut, da man dann um jede Funktion noch extra einen try finally Block einfügen muß, der sich um den Referenzzähler kümmert. Und Strings fallen gerade wenn es kein Textadventure ist, nicht unbedingt so furchtbar ins Gewicht. Zeiger auf Methoden fehlen auch, aber es gibt die message Methoden, so daß man das Verhalten nachbilden kann. Das mit dem Debuggen ist momentan nur über das Delphi CPU Fenster möglich. Es geht hierbei nicht darum Object Pascal vollständig nachzubilden, denn das wäre bei Scripts ein nicht gerechtfertigter Aufwand. Die Hauptidee ist möglichst einfach zu scripten und das geht am Besten wenn man direkt nativen Code benutzt. Da es aufwändig wäre in eine OOP Anwendung die Scripts als Funktionen zu haben, müssen sie eben auch Klassen unterstützen. Das Hauptziel ist hierbei Kompatibilität zu Delphi Programmen. Ich bin eigentlich gegen Kompromisse, aber da es ja hauptsächlich um OpenGL geht ist das Script nur ein Randgebiet, in dem man sich auch nicht ewig aufhalten will. Der erzeugte Maschinencode ist nicht so optimiert wie der von Delphi. Eine offentsichtliche Idee ist einfach mit push und pop zu arbeiten, als wenn die CPU nur auf dem Stack rechnen könnte. Das ist natürlich nicht die ganz optimale Lösung. Daher werden die Register eax und edx benutzt um alle Wert zu speichern und edi und esi um die Addressen während der Berechnung zu speichern. Wenn die Addresse oder Wert direkt feststeht, wird er natürlich nicht erst in die Register geladen. Bei einer lokalen Zuweisung wird natürlich direkt MOV [ebp+OFFSET],Wert erzeugt.
Die Zeile result:=result+i wird zu:
Code:
  1. mov eax,[ebp-$0000000C]
  2. add eax,[ebp-$00000010]
  3. mov [ebp-$0000000C],eax

Falls die Register nicht ausreichen kommt der Wert dann doch auf den Stack. EBX wird in Schleifen verwendet und ECX ist ein allgemeines Temp Register. Also vom perfekten Compiler oder der idealen Scriptsprache ist das weit entfernt, aber für den Einsatzbereich in Spielen/Engines durchaus geeignet, vermutlich schneller als PCode basierende Lösungen und mit einem guten Verhältnis zwischen Aufwand und Nutzen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Mai 02, 2004 14:09 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Dez 13, 2002 12:18
Beiträge: 1063
Die Idee gefällt mir wirklich gut: man erstellt sich einmal eine Schnittstelle im Programm, und kann diese dann zur Laufzeit mit Funktionen aus dem Skript "befüllen", dessen Code man ja auch in Delphi selbst entwickeln kann, wenn man sich an den Funktionsumfang des Skriptkompilers hält. Und das Ganze fast mit der Geschwindigkeit des nativen Delphikompilers - ich würde sagen, das ist eine tolle Anwendung von OOP, die den Code auch nicht unnötig aufbläht (die Basis von Innerfuse Pascal Script ist z.B. über 100000 Zeilen lang, was für "nur Skript Funktionalität" schon fast übertrieben ist, zumal wenn es wirklich nur darum geht, einige Methoden dynamisch zu überschreiben).

Eine Frage stellt sich mir allerdings noch: wie bekommt man Funktionalität aus dem Delphi-Programm ins Skript (etwa wenn man das Skript einige OpenGL Befehle ausführen lassen möchte, bzw. eine Methode ausführen lassen möchte, die direkt in Delphi auscodiert wurde)?

_________________
Viel Spaß beim Programmieren,
Mars
http://www.basegraph.com/


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Mai 02, 2004 14:33 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Das Projekt ist noch nicht ganz fertig und in nächster Zeit wird es dann noch Updates und Dokumentation geben während ich das ganze integriere. Das ist aber denke ich auch in Ordnung weil ja hier im Projekt die Entwicklungsschritte und nicht fertige Programme gezeigt werden sollen. Es ist durchaus möglich, daß sich dabei die Abwärtskompatibilität nicht mehr gewährleistet werden kann. Das ist hier also nicht als Release oder Demo sondern als Test zu sehen. Ich denke auch nicht, daß das so sehr dafür geeignet ist die VCL zu scripten, sondern eher so für Spiele. Dann speichert man den Klassennamen als Teil der Konfiguration und kann so auch viele verschiedene Elemente gleichzeitig und unabhängig wie bei den Mutators in UT ersetzen.
In der Funktion InitSystemUnit in der Datei dp_code.pas ist ein Beispiel wie die Unit System erstellt wird. Desweiteren gibt es noch die Variable OnLoadUnit:TOnLoadUnitFunc die auf eine Funktion zeigt, die einen Unit Namen übergeben bekommt und einen Stream mit dem Quelltext zurückgeben sollte.
Um einen ordentlichen Konstruktor und Destruktor erstellen zu können, werden die Zeiger auf die internen Funktionen ClassCreate, ClassDestroy, AfterConstruction und BeforeDestruction benötigt. Diese Zeiger werden direkt auf dem Code von TObject.Create und TObject.Destroy gelesen. Das Problem ist, daß das für andere Delphi Versionen eventuell angepaßt werden muß, aber dafür hat man dann einen richtigen Delphi Konstruktor und virtuelle Konstruktoren sind insbesondere im Zusammenhang mit Klassenreferenzen eine sehr wichtige Sache.
Um Delphi Funktionen aufzurufen gibt es mehrere Möglichkeiten. Man kann einer Unit direkt die Funktionen hinzufügen oder eine Klasse registieren die diese Funktionen bereitstellt. Wenn man sowieso eine Klasse von einer Delphi Klasse ableitet, dann kann man die geerbten Methoden ganz normal verwenden. Im Moment fehlt das Schlüsselwort inherited allerdings noch.
Die veröffentlichen Variablen eines Objektes kann man übrigens auch mit den Standard RTTI Funktionen aus der Unit TypeInfo lesen und schreiben.

Die Unit System wird folgendermaßen initialisiert. Hier wurden jetzt die Deklarationen der primitiven Typen weggelassen. Die jeweiligen Methoden haben lange Parameterlisten mit vielen Default Parametern und Überladungen. Die UnitInfos werden beim Programmende automatisch entfernt.

Code:
  1. with TUnitInfo.create('System') do
  2. begin
  3.  InterfaceSec:=true;
  4.  cls:=AddClass('TObject',nil);
  5.  cls.fclassptr:=TPersistent;
  6.  cls.AddMethod('Create',mtconstructor,fspublic,@TObject.Create);
  7.  cls.AddMethod('Free',mtprocedure,fspublic,@TObject.Free);
  8.  cls.fsize:=4;
  9.  cls.finstsize:=4;
  10.  cls.vmtsize:=3;
  11.  with cls.AddMethod('Destroy',mtdestructor,fspublic,@TObject.Destroy) do
  12.  begin
  13.   Flags:=Flags+[sfvirtual];
  14.   fvmtindex:=-1;
  15.  end;
  16.  with cls.AddMethod('Dispatch',mtprocedure,fspublic,@TObject.Dispatch) do
  17.  begin
  18.   Typeinfo.AddParam('Message',System_Untyped,ptvar);
  19.   Flags:=Flags+[sfvirtual];
  20.   fvmtindex:=-5;
  21.  end;
  22. end;
  23. end;


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Mai 03, 2004 07:54 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Jul 12, 2002 07:15
Beiträge: 916
Wohnort: Dietzhölztal / Hessen
Programmiersprache: C/C++, Obj-C
Sieht wirklich vielversprechend aus. Was ich persönlich praktisch finden würde (aber wahrscheinlich nur mit größerem Aufwand geht): Interfaces. Denn dann könnte man z.B. Die Klassen aus seinem Spiel per Interfaces freigeben (damit man die Klassen z.B. in DLLs packen kann) und im Script selber verwenden. Ich persönlich verwende in meinen kommenden Projekten nur noch interfaces. Ist zwar ein bischen mehr Tipp-Aufwand, aber dennoch Praktisch da ein Interface erst dann freigegeben wird, wenn die letzte Referenz darauf auf NIL gesetzt wurde. Damit ist die vorgehensweise z.B. prädestiniert für 'nen Textur-Manager. (Und unter Delphi absolut simpel zu verwenden!)

Das nur so als Gedankenanstoß.

_________________
Und was würdest Du tun, wenn Du wüsstest, dass morgen Dein letzter Tag auf dieser Erde ist?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Mai 03, 2004 13:18 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Ja Interface sind eine wirklich tolle Sache und meiner Meinung nach die einzig sinnvolle Verwendung von Mehrfachvererbung. Man muß dann eben für jedes Interface noch eine extra VMT erstellen. Es ist vielleicht gar keine schlechte Idee das noch einzubauen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Jul 29, 2004 15:32 
Offline
DGL Member
Benutzeravatar

Registriert: So Mai 11, 2003 10:36
Beiträge: 285
Wohnort: Oldenburg
Programmiersprache: Object Pascal
ich habe mal eine frage:
ich habe mir einen kleinen breakOut clone geschirben nun möchte ich gerne dein "scrip paser" verwenden.
ich habe eine klasse die sieht so aus:
Code:
  1.  
  2. type
  3.   TGrad = (GR_NONE, GR_FO, GR_MB);
  4.   TBO = class
  5.     constructor Create(GrafikL:Integer;F1:TForm;G:TGRAD);
  6.   public
  7.     GFL:TGrafik;
  8.     Grad:TGrad;
  9.     function GetMapSize:TMapSize;
  10.     procedure SetPlayerPos(x,y:Integer);
  11.     procedure SaveLevel(FileName:TFileName);
  12.   private
  13.     DownKeyTime:Integer;
  14.     TimeG:Integer;
  15.     Player:TPlayer;
  16.     Ball:array of TBall;
  17.     Items:array of TItems;
  18.     Steine:Array[0..MapX, 0..MapY] of TMap;
  19.     ran:Integer;
  20.     procedure Draw;
  21.     procedure CheckKey;
  22.     procedure MoveBall(Index,Speed:Integer);
  23.     procedure ClearSteine;
  24.     procedure CreateStein(x,y,Tex:Integer);
  25.     function AddGegener(x,y,tex,sTyp:Integer;typ:String):Boolean;
  26.     function CheckGPos(x,y:Integer):Boolean;
  27.     procedure ADD_BALL(px,py:Integer);
  28.     procedure DeleteBall(Index:Integer);
  29.   end;
  30.  


und hätte ich z.b. gerne folgendes scrip erstellt:


Code:
  1.  
  2.  
  3. procedure CheckFrame
  4. begin
  5.   if Player.x = 10 then Add_Ball(random(MAPX), random(MapY));
  6. end;
  7.  
  8.  


z.b.

ich verstehe jetzt noch nicht ganz wie ich das ausführen kann und das bei jedem Frame

_________________
MFG<br> Michael Springwald, <br>
Bitte nur Links in Deutsch, nutze überwiegend Lazarus


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Foren-Übersicht » Sonstiges » Meinungen zu den Projekten


Wer ist online?

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


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 16 Queries | GZIP : On ]