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

Aktuelle Zeit: Sa Jun 24, 2017 21:42

Foren-Übersicht » Sonstiges » Community-Projekte
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 26 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
 Betreff des Beitrags: OpenGL Import für Delphi .Net
BeitragVerfasst: So Feb 22, 2004 22:23 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Seit einiger Zeit gibt es ja Delphi auch für das .Net Framework. Es gibt bereits OpenGL Bindings für Delphi .Net, aber die sind nicht unbedingt einfach erweiterbar und kapseln nur eine C++ DLL oder rufen die Extension Funktionen auf seltsame Art und Weise auf (CSGL). Der Nachteil ist, daß die entsprechenden Assemblies und die DLL immer mit kopiert werden müssen und man letztlich nicht genau an den Inhalt kommt. Eine Delphi Unit kann auch bei Delphi .Net statisch gelinkt werden.

Auch in .Net Programmen können DLL Funktionen ohne Probleme importiert werden und auch CallBacks sind erlaubt. Daher kann man die OpenGL DLL's ohne Probleme mit LoadLibrary laden und auch GetProcAddress und wglGetProcAddress verwenden. Das Problem sind die Extensions die über einen Zeiger aufgerufen werden. Auch in Delphi.Net gibt es noch die Referenzen auf Funktionen und Prozeduren. Die Frage ist, ob man die als Rückgabetype bei einer importierten Funktion verwenden darf. In C# geht das nicht und es soll der Hilfe nach im .Net Framework erst ab der nächsten Version möglich sein.
Aber Delphi Assemblies können im Gegensatz zu C# Assemblies auch ganz normal aus Win32 Anwendungen als DLL angesprochen werden ohne das ein COM Wrapper benutzt werden muß. Es könnte also möglich sein, daß Delphi auch bei den Funktionszeigern mehr Möglichkeiten bietet. Es würde ja schon reichen wenn der Typecast von Integer zu so einem Zeiger möglich wäre. Ich besitze Delphi .Net leider noch nicht und konnte es nur kurz ausprobieren. Wenn jemand damit zu tun hat, könnte er ja mal testen ob das geht, dann wäre an dem Header ja nicht viel zu ändern.

Falls das nicht möglich ist, dann wäre immer noch die Möglichkeit eine DLL zu benutzen, die den Funktionsaufruf nur weiterleitet. Das ist immer noch besser als alle Funktionen in die DLL zu packen, weil die ja aus Delphi .Net nicht geändert werden kann. Die DLL müßte nur eine Funktion besitzen:
Code:
  1. procedure Invoke;stdcall;
  2. asm
  3.  pop ecx;
  4.  pop edx;
  5.  push ecx;
  6.  jmp edx;
  7. end


Man würde wglGetProcAddress einen Integer Wert zurückliefern lassen und den als ersten Parameter der Funktion übergeben. Alle dynamisch geladen Funktionen sind dann Importe dieser Funktion. Immer mit einer anderen Parameterliste und beim Aufruf nimmt man dann eben die tatsächliche Addresse als ersten Parameter. Das funktioniert zumindest in C# ganz gut und sieht so aus:

Code:
  1. [DllImport("invoke.dll", EntryPoint="Invoke")]
  2. private static extern int wglGetProcAddress_f(int funcptr,String funcname);
  3.  
  4. int LibHandle=LoadLibrary(OpenGLDLL);
  5. int wglGetProcAddress_p=GetProcAddress(LibHandle,"wglGetProcAddress");
  6. wglGetProcAddress_f(wglGetProcAddress_p,funcname);


Eine solche Funktion wird bereits bei Java benutzt. So daß man ohne externe DLL darauf zurückgreifen könnte.Das Problem ist, daß ab WinXP Java nicht mehr vorrausgesetzt werden kann.

Die zweite Möglichkeit wäre mit Hilfe der ILCodeGenerator Klasse dynamisch die Funktionen zur Laufzeit zu Generieren. Dann könnte man eventuell nur mit einer Delphi Unit auskommen. Ich bin mir nicht ganz sicher, ob man das möglich ist, weil die Extension Funktionen ja keine normalen DLL Importe, sondern im Prinzip beliebige Zeiger sind.

Falls jemand Delphi .Net bereits einsetzt, würden mich mal die Erfahrungen interessieren. .Net ist auf jeden Fall durchdacht und gelungen und daher ist es auch wichtig, daß Delphi jetzt diesen Schritt gemacht hat. Das Managed DirectX ist vom Aufbau dank der Properties sauber und auch übersichtlich und vor allem im Gegensatz zu OpenGL einfach verfügbar. Das Problem ist, daß OpenGL dort Bedeutung verlieren könnte. Daher sollte man vielleicht sich speziell um Delphi .Net kümmern, so daß OpenGL so einfach wie bisher auch unter .Net benutzt werden kann.


Zuletzt geändert von LarsMiddendorf am So Feb 22, 2004 23:37, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Feb 22, 2004 23:19 
Offline
Fels i.d. Brandung
Benutzeravatar

Registriert: Sa Mai 04, 2002 19:48
Beiträge: 3735
Wohnort: Tespe (nahe Hamburg)
Ich habe das hier eben gerade einmal gelesen und gestehe mir wirklich ein, dass ich mich unbedingt in den nächsten Wochen noch einmal Intensiv mit .NET befassen muss, ich konnte nämlich noch nicht den ganzen Ausmaß der Problematik erfassen... stimme Dir nur zu :roll: :wink:

Falls niemand aus dem Team bisher über Delphi.NET verfügen sollte, könnten wir durchaus auch mal riskieren einen öffentlichen Aufruf dazu zu machen, damit Du eventuell einen Test finden kannst. Vielleicht ist ja auch McClaw bereit Dir zu helfen, der verfügt ja bereits über Delphi.NET.
just my six cent.

_________________
"Light travels faster than sound. This is why some people appear bright, before you can hear them speak..."


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Feb 11, 2005 14:22 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Es wird wohl doch noch bis Ende März mit der PE Version zu dauern. Dann werd ich mal ausprobieren, wie man da sinnvoll einen Header machen kann. Einige Methoden habe ich ja schon vor einem Jahr mit C# getestet. Aber an dem .Net compiler sind glaube ich nur wenige Änderungen vorgenommen worden. Ist auf jeden Fall notwenig, denn das Managed DX ist mittlerweile nicht schlecht geworden und so langsam scheint das Interesse an .Net zu steigen. Wundere mich nur, dass die ganzen DX'ler das nicht benutzen, denn unter .Net hat OpenGL im Moment definitiv schlechtere Chancen. Wenn man mal im Netz danach sucht, findet man ja auch nur sehr wenige Projekte.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Feb 14, 2005 19:48 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Habe in C# mal ein wenig herumprobiert und mir ist es gelungen, aus einem Zeiger auf eine externe Methode ein Delegate zu erzeugen. Unter .Net 2.0 gibt's dafür die Methode Marshal.DelegateFromFunctionPtr, aber unter .Net 1.1 ist das nicht so einfach möglich. Delegates sind die normalen procedure/function Typen unter .Net .
Zuerst wird ein neuer Type erstellt und dynamisch mit dem ILGenerator eine Wrapper Methode generiert, die zu der Addresse springt. Die Addresse wird dabei direkt eingetragen. In dem Beispiel kommt sie von GetProcAddress, aber bei OpenGL würde man dann wglGetProcAddress verwenden. Zu dieser Methode wird dann ein Delegate Object erzeugt, das ganz normal wie eine normale procedure verwendet werden kann. Da es unter C# funktioniert, wird es wohl auch unter Delphi .Net funktionieren und so bestehen gute Chancen, dass der Header auch auf .Net portiert werden kann. Man müßte das nur mal in Delphi .Net eingeben. Ich habe es nicht.

Code:
  1. using System;
  2. using System.Reflection;
  3. using System.Reflection.Emit;
  4. using System.Threading;
  5. using System.IO;
  6. using System.Runtime.InteropServices;
  7.  
  8. namespace Project3
  9. {
  10.  
  11.     delegate int MessageBoxA(int hwnd,string title,string text,int buttons);
  12.  
  13.     class Loader
  14.     {
  15.         private AssemblyBuilder asmbuilder;
  16.         private ModuleBuilder modbuilder;
  17.         private int libhandle;
  18.  
  19.         [DllImport("Kernel32.dll")]
  20.         private static extern int LoadLibrary(string filename);
  21.  
  22.         [DllImport("Kernel32.dll")]
  23.         private static extern int GetProcAddress(int lib,string name);
  24.  
  25.         public System.Delegate CreateDelegate(string name,Type delegatetype)
  26.         {
  27.             MethodInfo d=delegatetype.GetMethod("Invoke");
  28.             Type[] paramlist=new Type[d.GetParameters().Length];
  29.             for(int i=0;i<paramlist.Length;i++)
  30.             {
  31.                 paramlist[i]=d.GetParameters()[i].ParameterType;
  32.             }
  33.             TypeBuilder t=modbuilder.DefineType(name);
  34.             MethodBuilder m=t.DefineMethod("Invoke",MethodAttributes.Static|MethodAttributes.Public,d.ReturnType,paramlist);
  35.             ILGenerator ilgen=m.GetILGenerator();
  36.             for(int i=0;i<paramlist.Length;i++)
  37.             {
  38.                 ilgen.Emit(OpCodes.Ldarg,i);
  39.             }
  40.             int addr=GetProcAddress(libhandle,name);
  41.             ilgen.Emit(OpCodes.Ldc_I4,addr);
  42.             ilgen.EmitCalli(OpCodes.Calli,CallingConvention.StdCall,d.ReturnType,paramlist);
  43.             ilgen.Emit(OpCodes.Ret);
  44.             Type t2 = t.CreateType();
  45.             MethodInfo m2=t2.GetMethod("Invoke");
  46.             return Delegate.CreateDelegate(delegatetype,m2);
  47.         }
  48.  
  49.         public Loader(string filename)
  50.         {
  51.             AssemblyName asmname=new AssemblyName();
  52.             asmname.Name=Path.GetFileNameWithoutExtension("Temp");
  53.             asmbuilder=Thread.GetDomain().DefineDynamicAssembly(asmname,AssemblyBuilderAccess.Run);
  54.             modbuilder=asmbuilder.DefineDynamicModule("Temp");
  55.             libhandle=LoadLibrary(filename);
  56.         }
  57.  
  58.     }
  59.  
  60.     class Class
  61.     {
  62.         [STAThread]
  63.         static void Main(string[] args)
  64.         {
  65.             Loader l=new Loader("User32.dll");
  66.             MessageBoxA m=(MessageBoxA)l.CreateDelegate("MessageBoxA",typeof(MessageBoxA));
  67.             Console.WriteLine(m(0,"Titel","Text",3));
  68.             Console.ReadLine();
  69.         }
  70.     }
  71. }


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Feb 18, 2005 20:51 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Ich habe das mal auf Delphi .Net portiert. Auch hier nur als Bsp. mit MessageBoxA.
Jedenfalls kann man so auch einen nativen Zeiger in eine Delegate konvertieren und das alles typesicher und ohne unsicheren Code.

Zitat:
TMessageBox=function(hwnd:Integer;title,text:string;flags:Integer):Integer;

procedure TWinForm.Button1_Click(sender: System.Object; e: System.EventArgs);
var
libhandle,ptr:Integer;
msgbox:TMessageBox;
begin
libhandle:=LoadLibrary('User32');
ptr:=GetProcAddress(libhandle,'MessageBoxA');
msgbox:=TMessageBox(CreateDelegate(ptr,TypeOf(TMessageBox)));
msgbox(0,'Title','Text',2);
end;


Das komplette Bsp. Projekt als Anhang.


Dateianhänge:
OpenGL.zip [17.38 KiB]
45-mal heruntergeladen
Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Feb 22, 2005 17:47 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Ich habe jetzt den dglopengl Header angepaßt, so dass es zumindest in Grundzügen bereits unter Delphi 2005, also .Net 1.1 funktioniert. Dazu mußten alle anonymen Funktionsdeklarationen Typen bekommen, damit später ein Delegate erstellt werden kann. Es wurde viel geändert, aber es scheint auch mit dem normalen Win32 noch zu funktionieren. Das Laden der Extensions ist nicht so schnell, immerhin wird für jede Funktion ein Wrapper dynamisch kompiliert und intern erzeugt .Net auch noch einen zusätzlichen Prozess. Dafür hat man das jetzt als Delphi Unit fast wie gewohnt und braucht keine Assemblies und zusätzlichen DLL's.


Dateianhänge:
dglOpenGL.zip [94.51 KiB]
49-mal heruntergeladen
delphi2005gl.PNG
delphi2005gl.PNG [ 109.79 KiB | 1828-mal betrachtet ]
Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Feb 23, 2005 15:40 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Habe die Version nochmal geupdatet und zwar wird der Type der Delegate direkt mit typeof und nicht mehr mittels Reflection ermittelt, was leicht schneller sein sollte. Leider ist in fast jeder Zeile jetzt ein {$IFDEF CLR}, aber dafür hat man jetzt einen Header für .Net,Win32 und Linux.
Interessanterweise scheinen die Pointer Deklarationen nichts auszumachen. Erst wenn sie verwendet werden, wird dann unsafe verlangt, was aber eigentlich bei OpenGL nie nötig sein sollte.


Dateianhänge:
dglOpenGL.zip [100.26 KiB]
44-mal heruntergeladen
Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Feb 23, 2005 20:03 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5797
Programmiersprache: C++
Daumen hoch! Hab das leider noch nicht probiert (warte noch auf die PE), aber ein einzelner Header für Win32/.NET/Linux/Andere Pascal-Compiler dürfte ne geniale Sache sein. In wie weit ist der denn praxistauglich? Evtl. kann man ja nen öffentlichen "Betatest" starten und den Header dann endgültig als offiziell anbieten.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Feb 23, 2005 20:44 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Ja da gibt's noch einige Punkte, bis dass wirklich 100% einsetzbar ist.
Man wird vermutlich bei einigen Funktionen noch die Pointer durch Arrays ersetzen müssen, was ja auch Sinn macht, denn bei den Funktionen mit Pointern z.B. glVertex3fv sind ja in der C Welt auch Arrays gemeint gewesen. Also so wie beim C# Header auch. Momentan gibt's bei Funktionen mit Pointern beim Generieren von dem Delegate Type eine Exception mit dem Ergebnis, dass die Funktionen dann auf nil gesetzt werden.

Das Laden aller Extensions dauert ca 3-4 Sekunden, was definitiv zu lang ist. Es muß an der dynamischen Generierung liegen. Da muß man sich nochmal was einfallen lassen. Es gibt aber soweit ich das Netz abgesucht habe, keine andere Möglichkeit und es gibt ja sowieso keinen OpenGL Header, der nicht auf externe DLL's zurückgreift und unter .Net 1.1 schon gar nicht. Das ist halt schön, wenn man das direkt miteinkompilieren kann.

Wenn Delphi auch .Net unterstützt wird kaum was geändert werden müssen, da es ja bereits jetzt auf die Delegates ausgelegt ist, nur mit dem Unterschied, dass man dann diese ganze Sache mit dem Generieren sein lassen kann und die Zeiger sauber und einfach direkt konvertieren kann.

Ich werde das Template nach WinForms portieren.

Wie man sieht, es geht obwohl es nicht so schön elegant ist wie unter Win32. Ich werd sehen, was ich an diesen Punkten da noch verbessern kann, bis die PE rauskommt. Das Problem ist nämlich, dass es mit DX unter .Net ganz ohne Schwierigkeiten geht und wenn man da nicht zeitig was anbietet, werden die OpenGL Leute entweder bei Win32 bleiben oder zu DX wechseln, was beides nicht so toll ist.
Obwohl die reduzierte Delphi2005 Version doch schneller ist, ist sie einige Male hängen geblieben und hat teilweise Quelltext mitgerissen, so dass meine Hoffnungen für Delphi2005 schon wieder stark getrübt sind.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Feb 23, 2005 22:14 
Offline
DGL Member

Registriert: Do Mai 30, 2002 18:48
Beiträge: 1616
LarsMiddendorf hat geschrieben:
Obwohl die reduzierte Delphi2005 Version doch schneller ist, ist sie einige Male hängen geblieben und hat teilweise Quelltext mitgerissen, so dass meine Hoffnungen für Delphi2005 schon wieder stark getrübt sind.

Irgendwo in den Editoroptionen kann man diese neien, aufpoppenden fensterchen abklemmen, die zu den Programmierhilfen gehören. Mich ahben sie eh mehr gestört, als dass sie mir etwas gebracht hatten, darum war ich eigentlich froh drum, als ich den hebel gefunden hatte. Nachdem ich das gemacht hatte, waren auch keine Abstürze mehr zu beklagen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Feb 23, 2005 22:22 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Aha gut, werd ich mal ausprobieren. Vielleicht ist es ja dann auch schneller.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Feb 25, 2005 10:35 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Die Extensions dauern ja wie gesagt lange zu laden. Wäre es akzeptabel, wenn man da eine globale Variable einbaut, mit der man angeben kann, dass nur die ARB Extensions geladen werden? Die allermeisten verwenden die Extensions doch sowieso nur sehr spärlich und wenn dann hauptsächlich ARB.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Feb 25, 2005 11:45 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Also das finde ich nicht so sonderlich gut. Dann wäre ich eher dafür, dass man das macht wie Tom Nuydens. Also, dann explizit angibt welche Extensions geladen werden sollen. Denn auch die ARB's werden mehr und dann hätte man genau das selbe Problem.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Feb 25, 2005 14:26 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Das ist die andere Möglichkeit, obwohl man dann nicht mehr das automatische Laden bei ActivateRenderingContext hätte.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Feb 25, 2005 15:38 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Das könnte man ja dann evtl. per optionalem Parameter immernoch anbieten. Also, dass er dann alle Extensions lädt. Der könnte bei .NET standard auf False stehen und bei allem anderen auf True. Allerdings birgt das ganze dann natürlich noch ein größres Problem. Alle bisher geschriebenen Programme müssten angepasst werden. Ich denke mal, wenn wir eine Änderung an der Schnittstelle und Funktionsweise durchführen dann sollte die Endgültig und sehr gut überlegt sein! Auf keinen Fall sollten wir da aus einer Laune herraus das immer und immer wieder anpassen und ändern. Die Benutzer des Header werden im Dreieck springen. Und ich kann die Fragen jetzt schon hören. ;-)


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 26 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Foren-Übersicht » Sonstiges » Community-Projekte


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


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:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.036s | 20 Queries | GZIP : On ]