DLL Aufruf mit Blitz Max

Übersicht BlitzMax, BlitzMax NG FAQs und Tutorials

Neue Antwort erstellen

Suco-X

Betreff: DLL Aufruf mit Blitz Max

BeitragMo, Jun 06, 2005 7:24
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Sep 15, 2009 17:16
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMi, Sep 16, 2009 15:52
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, Aug 28, 2010 9:09
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, Aug 28, 2010 13:40
Antworten mit Zitat
Benutzer-Profile anzeigen
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

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG FAQs und Tutorials

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group