PureBasic: Code-Auslagerung

Sobald Projekte eine gewisse Größe erreichen, wird es sinnvoll den Code auf mehrere Dateien aufzuteilen.

ausgelagert.pb

Procedure ausgelagert()
  PrintN("Ich bin eine ausgelagerte Prozedur")
EndProcedure

main.pb

; Listing 32: Code-Auslagerung

IncludeFile "./ausgelagert.pb"

OpenConsole()

ausgelagert()

Delay(2000)
Ausgabe:

Ich bin eine ausgelagerte Prozedur

Nachdem man den Code in die zwei Dateien eingetippt und im gleichen Ordner abgespeichert hat, kann die Prozedur ausgelagert() in der Hauptdatei aufgerufen werden. Dies liegt am Schlüsselwort IncludeFile, dass den Inhalt der übergebenen Datei an genau dieser Stelle einfügt. Als Ausdruck wird ein String benötigt, der den Pfad zur ausgelagerten Datei enthält. Theoretisch kann man auch normale Befehle, Variablen, Arrays etc. auf diese Weise auslagern, normalerweise lagert man aber Prozeduren aus, die aus der Hauptdatei aufgerufen werden sollen.

Mit dem Schlüsselwort XIncludeFile wird das Gleiche erreicht, jedoch verhindert dieses im Gegensatz zum anderen, dass eine Datei mehrmals eingefügt wird.

BibliothekenBearbeiten

Die obere Variante bietet sich bei Software-Projekten an, bei welchen der ausgelagerte Code speziell für dieses Projekt entwickelt wurde. Wenn man jedoch Prozeduren schreibt, die von vielen Programmen benutzt werden können, erstellt man normalerweise eine Bibliothek. Ein Beispiel für solch eine Bibliothek ist z.B. die Befehlsbibliothek mit mathematischen Befehlen für PureBasic.

Bibliotheken haben einige Vorteile gegenüber der ersten Variante. So wird der Bibliothekscode, auch wenn er von mehreren Programmen gleichzeitig benutzt wird, nur einmal geladen, die Ressourcen des Computers werden also effektiver genutzt. Außerdem ist der Speicherplatz einer gespeicherten Bibliothek geringer, da diese auf dem Computer in kompilierter Form vorliegen. Unter Windows sind dies die .dll-Dateien, unter Linux die .so-Dateien und unter Mac OS X die .dylib-Dateien.

In eine Bibliotheksdatei schreibt man normalerweise nur Prozeduren, auch wenn anderes möglich wäre. Man unterscheidet zwischen privaten und öffentlichen Prozeduren. Die privaten können nur innerhalb der Bibliothek benutzt werden, öffentliche auch von Programmen, die die Bibliothek benutzen. Eine private Prozedur wird wie eine normale Prozedur mit Procedure geschrieben, für eine öffentliche benutzt man hingegen ProcedureDLL.

Nachfolgend soll nun ein einfaches Beispiel folgen.

dll-datei.pb

ProcedureDLL test(x.l)
  OpenConsole()
  PrintN("Ich bin eine DLL-Datei und bekam als Argument "+Str(x)+" übergeben")
  Delay(2000)
EndProcedure

main.pb

; Listing 33: DLL-Dateien

Prototype Test(x.l)
OpenLibrary(0, "./test.dll")
dllFunction.Test = GetFunction(0, "test")
dllFunction(2)
CloseLibrary(0)
Ausgabe:

Ich bin eine DLL-Datei und bekam als Argument 2 übergeben

Die Datei dll-datei.pb muss erst als .dll-Datei kompiliert werden. Dazu wählt man Compiler->Compiler-Optionen... und stellt hier unter Executable-Format Shared Dll ein und damit das Ü richtig dargestellt wird sollte auch Unicode-Executable erstellen eingehackt werden. Nun wählt man Compiler->Executable erstellen... und speichert die .dll-Datei am gleichen Ort wie main.pb ab.

Wie man sieht, wird in dll-datei.pb eine öffentliche Prozedur erstellt, die eine Konsole öffnet und einen String ausgibt. Nach 2 Sekunden geht die Programmausführung weiter.

In main.pb wird zuerst ein Prozedurprototyp deklariert. Dies ist ein Variablentyp, der eine Funktion repräsentiert. Der Prototyp muss die gleichen Argumente haben, wie die Prozedur der .dll-Datei. Nun öffnet man die Bibliothek mit OpenLibrary(). Das erste Argument ist hierbei eine Identifikationsnummer für die geöffnete Bibliothek. Als nächstes erstellt man eine Variable vom Typ des vorher deklarierten Prozedurprototyps mit GetFunction(). dllFunction ist hierbei ein Zeiger, was in einem späteren Kapitel erklärt wird. Soviel sei gesagt: GetFunction() gibt von einer bestimmten Bibliothek (hier Nummer 0), die vorher geöffnet und damit in den Arbeitsspeicher geladen wurde, die Adresse der Prozedur zurück, deren Namen GetFunction() übergeben bekommt. dllFunction() kann nun wie die Prozedur eigentliche Prozedur verwendet werden. Zuletzt schließt man die Bibliothek mit CloseLibrary().