DLL Aufruf mit Blitz Max
Übersicht BlitzMax, BlitzMax NG FAQs und Tutorials
Suco-XBetreff: DLL Aufruf mit Blitz Max |
Mo, Jun 06, 2005 7:24 Antworten mit Zitat |
|
---|---|---|
DLL Aufruf mit Blitz Max
Willkommen bei meinem Tutorial zum Thema "DLL Aufruf mit Blitz Max". Eine DLL ( Dynamic Link Library ) werdet ihr in Blitz Max aber höchstwarscheinlich nie auf diese Art nutzen müssen. Trotzdem ist es interessantes Wissen und besser man weiss zu viel als zu wenig. Los gehts. Was ist eine DLL? Da sich schon einige Leute die Mühe gemacht haben diese Informationen in einen Artikel zusammenzufassen, werde ich euch einfach den Link dazu geben und meine Tinte für das eigentliche Tutorial sparen. Link zum Artikel : http://de.wikipedia.org/wiki/B...mierung%29 genau durchlesen. Wie erstelle ich eine DLL? Eine DLL kann mit üblichen Hochsprachen wie C++/Delphi/Visual Basic erstellt werden. Die DLL die ich für dieses Tutorial geschrieben habe, wurde mit C++ angefertigt. Dazu habe ich mir die Faq von blitzbasic.com zu den Userlibs angeschaut. Dort wird beschrieben wie man eine DLL erstellt. Link zur Faq : http://www.blitzbasic.com/sdks..._specs.txt Anmerkungen: Blitz Max kann direkt C/C++ und Asm Code Importieren. Mit C++ eine DLL zu machen und diese dann, wie im folgenden Tutorial beschrieben, zu laden, ist sinnlos und bedeutet nur mehr Arbeit. Trotzdem reicht das ganze aus um zu zeigen wie der DLL Aufruf mit Blitz Max funktioniert. Desweiteren ist das DLL und C++ Gebiet für Programmier Anfänger nicht geeignet und würde wohl nur mehr verwirren. Als erstes der DLL Code den ich für die Beispiel DLL erstellt habe : Code: [AUSKLAPPEN] #include <stdlib.h> #define BBDECL extern "C" _declspec(dllexport) #define BBCALL _stdcall BBDECL void BBCALL SwapIntegers(int *integer1, int *integer2) { int temp = *integer1; *integer1 = *integer2; *integer2 = temp; } Die Funktion SwapIntegers erwartet als Parameter zwei Integer Pointer und tauscht deren Inhalt aus. Falls ihr keine Ahnung habt wie ihr die DLL erstellen könnt, hier die fertige Version http://www.sucox.art-fx.org/BmaxTestDll.dll Die DLL wurde im Release Modus erstellt und mit UPX weiter verkleinert. Jetzt BlitzMax starten und aufpassen. Ich werde den Code Stück für Stück auflisten und beschreiben. Am Ende folgt der komplette Code zusammengefasst. Code: [AUSKLAPPEN] Strict Framework brl.basic Import pub.win32 'Variablen Local DllName:String, DllHandle:Int Für den Test wird ein Framework mit zwei Modulen festgelegt, mehr wird nicht gebraucht. DllName und DllHandle werden weiter unten benutzt. Code: [AUSKLAPPEN] DllName = "BmaxTestDll.dll" DllHandle = LoadLibraryA(DllName) If DllHandle = 0 Print "Dll konnte nicht geladen werden" End EndIf Der DLL DateiName wird in DllName gespeichert und in DllHandle wird das Handle zur DLL gespeichert. LoadLibraryA ist eine WinAPI Funktion die mit dem pub.win32 Modul zur verfügung gestellt wird. Mit dieser Funktion wird eine DLL geladen und das handle dieser DLL Zurückgegeben falls sie geladen werden konnte. Wenn die DLL nicht geladen werden konnte, wird abgebrochen und die Fehlermeldung ausgegeben. Code: [AUSKLAPPEN] Global SwapIntegers(zahl1:Int Ptr, zahl2:Int Ptr)"Win32" = GetProcAddress(DllHandle,"_SwapIntegers@8") Wichtigste Zeile. Wir erhalten die Adresse zu der DLL Funktion mit GetProcAddress (Ebenfalls WinAPI Funktion aus dem pub.win32 Modul) und casten diese Adresse in unseren Funktionspointer. Das "Win32" gibt die Aufrufkonvention der Funktion an, stdcall. BlitzMax benutzt Standard wohl was anderes. Sollte das "Win32" vergessen werden, wird Blitz Max mit einem Absturz antworten. WICHTIG : Sollte eine DLL Funktion einen Funktionspointer als Parameter erwarten, muss diese Funktion ebenfalls mit "Win32" gekennzeichnet werden. Der aufmerksame Leser wird sich jetzt bestimmt noch eines Fragen. Im C++ Code heißt die Funktion "SwapIntegers", wieso kann man sie dann nur mit "_SwapIntegers@8" aus der DLL aufrufen? Wieso das "_" auf einmal verlangt wird, weiss ich nicht. Sollte es jemand wissen, bitte Posten. Das "@8" steht für die Bytes die für die Funktionsparameter gebraucht werden. Hier werden zwei Parameter a 4 Byte genutzt, ergibt 8. Code: [AUSKLAPPEN] Local Integer1:Int = 100 Local Integer2:Int = 700 Print "TEST 1 START" Print "Integer1: "+integer1 Print "Integer2: "+integer2 Print "Starte Tausch" SwapIntegers(Varptr Integer1, Varptr Integer2) Print "Tausch beendet" Print "Integer1: "+integer1 Print "Integer2: "+integer2 Print "TEST 1 ENDE" Zum Abschluss noch ein kleiner Test ob die Funktion auch korrekt aus der DLL geladen wurde und genutzt werden kann. ANHANG: Falls eine Funktion nicht korrekt aus der DLL aufgerufen werden konnte, sagt Blitz Max mit einer nichtssagenden Fehlermeldung Tschüss. Man weiss also nicht ob es jetzt ein Fehler im Code ist oder die Funktion beim zuweisen der DLL Funktion falsch geschrieben wurde. Dafür eine kleine Funktion von mir die Checkt ob die Funktionsadresse korrekt ist. Code: [AUSKLAPPEN] Function FunctionExists(func:Byte Ptr) If Int(func)<>0 Return True EndIf Return False End Function Die übergebene Funktionsadresse wird in ein Integer gecastet und wenn die Adresse 0 ist, exestiert die Funktion auch nicht. ANHANG2: Sollte eine DLL Funktion Pointer erwarten, kann man auch einfach :byte ptr für die Parameter benutzen. So, ich hoffe es war alles verständlich. Sollten dennoch weitere Fragen auftauchen, könnt ihr diese hier Posten. Hier noch der komplette Code: Code: [AUSKLAPPEN] Strict Framework brl.basic Import pub.win32 'Variablen Local DllName:String, DllHandle:Int DllName = "BmaxTestDll.dll" DllHandle = LoadLibraryA(DllName) If DllHandle = 0 Print "Dll konnte nicht geladen werden" End EndIf Global SwapIntegers(zahl1:Int Ptr, zahl2:Int Ptr)"Win32" = GetProcAddress(DllHandle,"_SwapIntegers@8") Function FunctionExists(func:Byte Ptr) If Int(func)<>0 Return True EndIf Return False End Function If FunctionExists(SwapIntegers) Print "Funktion SwapIntegers exestiert" Else Print "Funktion SwapIntegers konnte nicht aufgerufen werden" EndIf Local Integer1:Int = 100 Local Integer2:Int = 700 Print "TEST 1 START" Print "Integer1: "+integer1 Print "Integer2: "+integer2 Print "Starte Tausch" SwapIntegers(Varptr Integer1, Varptr Integer2) Print "Tausch beendet" Print "Integer1: "+integer1 Print "Integer2: "+integer2 Print "TEST 1 ENDE" Und nochmal Link zur DLL: http://www.blitzbasic.com/sdks..._specs.txt Mfg Suco |
||
Intel Core 2 Quad Q8300, 4× 2500 MHz, 4096 MB DDR2-Ram, GeForce 9600GT 512 MB |
Farbfinsternis |
Di, Sep 15, 2009 17:16 Antworten mit Zitat |
|
---|---|---|
Ich weiß dass dieser Fred hier schon ein paar Jahre auf dem Buckel hat, aber ich muss noch was erwähnen:
void myFunction(void) muss in BMax mit @0 geholt werden, sonst wird die Funktion nicht initialisiert. Man könnte davon ausgehen dass der Compiler automatisch erkennt dass ohne @0 keine Parameter erwartet werden, aber so ist BMax ... immer schön an der Wand lang. |
||
Farbfinsternis.tv |
ChristianK |
Mi, Sep 16, 2009 15:52 Antworten mit Zitat |
|
---|---|---|
Ob und welche Zahl man hinter dem @ angibt, hat nichts mit dem Compiler zu tun. Genau genommen ist die Anzahl der Parameter-Bytes auch völlig uninteressant für das Programm. Es kommt nur darauf an, wie der Compiler der DLL den Funktionsnamen exportiert. | ||
AdvanceLcd
Intel Core 2 Duo 3.2 GHz, 4 GB RAM, GeForce 8800 GTX | MacBook Pro 15,4″ Intel Core 2 Duo 2.4 GHz, 2 GB RAM, GeForce 8600M GT |
Peak7810 |
Sa, Aug 28, 2010 9:09 Antworten mit Zitat |
|
---|---|---|
Ich glaube mich erinnern zu können daß die Zahl hinter @ speicher reserviert abhängig vom Rückgabewert.
Der bei @0 null ist, da nur etwas an die dll übergeben wird aber kein Rückgabewert als solches erwartet wird. Kann mich aber auch iren ist schon länger her wo ich das gelesen habe. |
||
Thunder |
Sa, Aug 28, 2010 13:40 Antworten mit Zitat |
|
---|---|---|
Das _ steht vorne an der Funktion, weil die meisten C/C++-Compiler, so auch der aus GCC das _ als Präfix verwendet und vor jede globale Variable und Funktion stellt.
mfg Thunder |
||
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit |
Übersicht BlitzMax, BlitzMax NG FAQs und Tutorials
Powered by phpBB © 2001 - 2006, phpBB Group