|
|
|
|
Programmieren mit Pascal & DelphiArbeiten mit DelphiErste Schritte mit DelphiPackages Einführung
|
Eine Package-Quelltextdatei enthält keinerlei Typ-, Daten- Prozedur- oder Funktionsdeklarationen. Statt dessen enthält sie den Namen des Packages, eine Liste der erforderlichen Packages und die Namen der aufzunehmenden Quelltext-Units.
Zum Erstellen eines Packages sind folgende Angaben erforderlich:
- ein Name für das Package,
- eine Liste der anderen Packages, die vom neuen Package benötigt oder mit diesem verknüpft werden,
- eine Liste der Unit-Dateien, die beim Compilieren in das Package aufgenommen werden sollen.
Das Package selbst ist im wesentlichen eine "Verpackung" für die Quelltext-Units, die ihrerseits die Funktionalität in der compilierten DPL-Datei bereitstellen.
Package-Namenskonventionen
| | |
Für Package-Dateien gibt es unter Delphi feste Namenserweiterungen:
|
Erweiterung
|
Dateiformat
|
|
DKP
|
Package-Quelltextdateien
|
|
DPL
|
ausführbare Datei
|
|
DCP
|
Binär-Image
|
Das Anlegen eines neuen Packages erfolgt am einfachsten über den Package-Editor. Im ersten Schritt wird über Datei/ Neu das Format "Package" ausgewählt, so daß der Package-Wizzard erscheint und den Namen des Packages abfragt:
Abbildung 4/5.2.2.1-1: Namen für Package festlegen
Im Dialog "Neues Package" kann man einen Dateinamen und optional eine Beschreibung eingeben. Wird der Namen ohne einen Pfad angegeben, speichert Delphi das Package im aktuellen Verzeichnis.
Nach Bestätigen über "Ok" landet man im Package-Editor:
Abbildung 4/5.2.2.1-2: Package-Editor
Der Package-Editor bietet mehrere Register an, die folgende Funktionen haben:
| Namenserweiterungen |
|
Schaltfläche
|
Beschreibung
|
|
Compilieren
|
Mit dieser Schaltfläche wird das aktuelle Package compiliert. Sind Änderungen am Package erforderlich, wird ein Dialogfeld angezeigt, in dem die Änderungen überprüft werden können, bevor das Package compiliert wird.
|
|
Hinzufügen
|
Diese Schaltfläche fügt ein Element hinzu.
|
|
Entfernen
|
Diese Schaltfläche entfernt das ausgewählte Element aus dem Package.
|
|
Optionen
|
Diese Schaltfläche zeigt das Dialogfeld Optionen für Package an.
|
|
Installieren
|
Diese Schaltfläche installiert das aktuelle Package als Entwurfszeit-Package. Sind Änderungen am Package erforderlich, wird ein Dialogfeld mit den erforderlichen Änderungen angezeigt, bevor das Package compiliert wird.
|
|
Aktualisieren
|
Diese Schaltfläche aktualisiert den Package-Editor, damit die Änderungen an der DPK-Datei berücksichtigt werden. Sie wird aktiviert, nachdem die DPK-Datei mit dem Quelltext-Editor geändert wurde. Einträge im Package-Editor werden deaktiviert, nachdem die DPK-Datei geändert wurde, um auf diese Tatsache hinzuweisen.
|
Das Hauptfenster des Package-Editors zeigt die Units in einem Package sowie die für das Package erforderlichen Pakkages in zwei Unter-Registerseiten an.
|
Registerkarte
|
Inhalt
|
|
Enthält
|
Die Registerkarte Enthält zeigt die im Package enthaltenen Units an. Per Doppelklick auf eine Unit, kann deren Quelltext bearbeitet werden.
|
|
Benötigt
|
Die Registerkarte Benötigt zeigt die anderen Packages an, die vom aktuellen Package benötigt werden. Über die Schaltfläche Hinzufügen, wird ein Package eingefügt. Per Doppelklick auf ein Package gelangt man in den zugehörigen Package-Editor.
|
Über die Schaltfläche Hinzufügen kann eine Unit in das Package eingefügt werden. Der nun angezeigte Dialog besitzt drei Registerkarten, die drei verschiedene Typen von Module ansprechen:
- Unit,
- neue Komponenten,
- ActiceX-Komponente.
| Register des Package-Editors | |
Über die Registerkarte "Unit hinzufügen" werden bestehende Units, deren Name in das Feld Unit-Dateiname eingetragen wird, in die contains-Klausel eines Packages eingefügt. Der Dateiname kann mit Pfad angegeben oder der Suchpfad bearbeitet werden. Änderungen des Suchpfads wirken sich auf den globalen Bibliothekspfad von Delphi aus. Sollen mehrere Unit-Dateien in das Package eingefügt werden, ist der Vorgang entsprechend oft zu wiederholen.
| Unit hinzufügen | |
Die Registerkarte "Neue Komponente", erlaubt das Erstellen einer neuen Komponente. Hierzu sind analog zum Komponenten-Wizzard die folgenden Eingaben erforderlich:
- Klassenname,
- Name des unmittelbaren Vorfahren,
- Name der Unit-Datei für die Deklaration der Komponente,
- Registerkarte in der Komponentenpalette, auf der die Komponente angezeigt werden soll.
| Neue Komponente hinzufügen | |
Für das Importieren einer ActiveX-Komponente ist auf der Registerkarte ActiveX importieren im Listenfeld eine der registrierten Komponenten auszuwählen.
Abbildung 4/5.2.2.1-3: ActiveX-Komponenten verwalten
Über die Schaltflächen "Hinzufügen" und "Enfernen" kann eine neue Komponente registriert bzw. die Registrierung einer Komponente aufgehoben werden.
| ActiveX-Komponente importieren | |
Nach dem Hinzufügen der Units bzw. Komponenten können im Hauptfenster des Package-Editors auf der Registerkarte "Benötigt", die Liste der anderen Packages in der requires-Klausel des bearbeiteten Packages angezeigt und eingetragen werden. VCL30 wird standardmäßig angezeigt. Sollen weitere Packages in die requires-Klausel eingefügt werden, führt ein Mausklick auf "Hinzufügen" in einen Auswahldialog.
| Benötigte Packages | |
Die Art des Packages, das erstellt werden soll, legt man über die Optionen fest.
Abbildung 4/5.2.2.1-4: Package-Optionen
| Package-Einsatz | |
Unter "Verwenden als" stehen die Optionen
- Entwurfszeit-Package,
- Laufzeit-Package
bereit, wobei beide gleichzeitig angewählt werden können. Die Auswahl einer dieser Optionen aktiviert die Compiler-Direktive $RUNONLY oder $DESIGNONLY. Soll ein Entwurfszeit-Package erstellt werden, das nicht in der IDE installiert, aber von anderen Entwurfszeit-Packages aufgerufen werden kann, so ist die Markierung beider Kontrollkästchen zu entfernen.
| Package-Verwendung | |
Unter "Element compilieren" werden die Optionen
- bei Bedarf compilieren,
- manuell compilieren
angeboten. Die Option "Manuell compilieren" aktiviert den Compiler-Schalter -Z ($IMPLICITBUILD OFF), der die implizite Neucompilierung des Packages verhindert.
Mit Betätigen der Schaltfläche Compilieren in der Mauspalette wird das Package in eine DPL-Datei compiliert, die Package-Quelltextdatei (DPK) jedoch nicht gespeichert. Möchte man die .DPK-Datei speichern, klickt man mit der rechten Maustaste, und wählt "Package speichern", oder wählt Datei/Speichern im Hauptmenü von Delphi.
Package-Quelltextdateien manuell bearbeiten
Package-Quelltextdateien werden wie Projektdateien von Delphi aus den bereitgestellten Informationen generiert. Sie können auch wie Projektdateien manuell bearbeitet werden. Eine Package-Quelltextdatei sollte mit der Erweiterung .DPK (Delphi-Package) gespeichert werden, um Verwechslungen mit anderen Dateien zu vermeiden, die Object Pascal-Quelltext enthalten.
Der Quelltext einer Package-Datei wird wie folgt geöffnet:
- Zunächst ist das Package über den Package-Editor zu öffnen,
- anschließend öffnet ein Klick mit der rechten Maustaste ein Popup-Menü, in dem der Befehl "Package-Quelle" ausgewählt werden kann.
Ein Package kennt drei Schlüsselwörter:
|
Key
|
Bedeutung
|
|
package
|
Gibt den Namen des Package an.
|
|
requires
|
Die requires-Klausel gibt externe Packages an, die vom aktuellen Package verwendet werden. Referenziert ein Package keine anderen Packages, muß keine requires-Klausel angegeben werden.
|
|
contains
|
Die contains-Klausel bezeichnet die Unit-Dateien, die in das Package compiliert werden sollen.
|
Der folgende Quelltext deklariert beispielsweise das Package VCLDB30.
| Kompilation |
package VCLDB30;
requires VCL30;
contains Db, Dbcgrids, Dbctrls, Dbgrids,
Dbinpreq, Dblogdlg, Dbpwdlg,
Dbtables;
end.
Packages compilieren
Ein Package kann in der IDE oder von der Befehlszeile aus kompiliert werden. Wird ein Projekt mit einem Package neu kompiliert, wird das Package gegebenenfalls implizit neu kompiliert.
Die Auswahl der Packagedatei erfolgt über den Standard-Dialog zur Dateiauswahl, wobei als Dateityp "Delphi-Quell-Package (*.dpk)/*.dpk)" in der Dropdown-Liste Dateityp spezifiziert wird. Mit der Datei wird automatisch auch der Package-Editor geladen, über den dann das Kompilieren erfolgt.
| Beispiel-Quelltext | |
Das manuelle Bearbeiten der Package-Quelldatei bringt einige Vorteile mit sich. So kann man beispielsweise Package-spezifische Compiler-Direktiven in den Package-Quelltext einfügen.
Die folgende Tabelle enthält die Package-spezifischen Compiler-Direktiven, die aktuell unterstützt werden.
|
Direktive
|
Beschreibung
|
|
{$IMPLICITBUILD OFF}
|
Diese Direktive verhindert das spätere implizite Neucompilieren des Packages. Man verwendet sie primär in .DPK-Dateien mit grundlegender Funktionalität, die selten geändert werden oder deren Quelltext nicht weitergegeben wird.
|
|
{$G-} oder {IMPORTEDDATA OFF}
|
Diese Direktive deaktiviert die Erstellung importierter Datenreferenzen. Sie verbessert die Effizienz beim Speicherzugriff, verhindert aber die Referenzierung von Variablen anderer Packages in Units.
|
|
{$DENYPACKAGEUNIT ON}
|
Diese Direktive verhindert das Einfügen einer Unit in ein Package.
|
|
{$DESIGNONLY ON}
|
Diese Direktive compiliert das Package für die Installation in der IDE (wird in .DPK-Dateien verwendet).
|
|
{$RUNONLY ON}
|
Diese Direktive compiliert das Package als Laufzeit-Package (wird in .DPK-Dateien verwendet).
|
|
{$WEAKPACKAGEUNIT}
|
Die Direktive $WEAKPACKAGEUNIT bestimmt, wie eine .DCU-Datei in der .DCP-Datei und den .DPL-Dateien eines Package gespeichert wird. Befindet sich die Direktive {$WEAKPACKAGEUNIT ON} in einer Unit-Datei, wird die Unit vom Compiler (wenn möglich) nicht in die .DPL-Dateien eingefügt. Statt dessen wird außerhalb des Packages eine lokale Kopie der Unit erstellt, wenn diese von einer anderen Anwendung oder einem anderen Package benötigt wird.
|
| Compiler-Direktiven | |
Die Direktive {$DENYPACKAGEUNIT ON} im Quelltext verhindert die Aufnahme der Unit-Datei in ein Package. Mit {$G-} oder {IMPORTEDDATA OFF} kann die Benutzung des Packages zusammen mit anderen Packages in einer Anwendung verhindert werden. Mit der Direktive {$DESIGNONLY ON} compilierte Packages sollten normalerweise nicht in Anwendungen genutzt werden, da sie zusätzlichen Code enthalten, der von der IDE benötigt wird. Andere Compiler-Direktiven können bei Bedarf in den Package-Quelltext eingefügt werden. Informationen zu den hier nicht beschriebenen Compiler-Direktiven finden Sie in der Object-Pascal-Sprachreferenz.
| Einschränken der Kompilierung | |
Der Einsatz der Direktive {$WEAKPACKAGEUNIT} ist etwas komplizierter und läßt sich am besten durch ein Beispiel erklären. Angenommen, ein Package namens PACK enthält nur die Unit UNIT1. UNIT1 verwendet keine anderen Units, ruft aber RARE.DLL auf. Wird die Direktive {$WEAKPACKAGEUNIT ON} in UNIT1.PAS eingefügt, bevor das Package compiliert wird, so wird UNIT1 nicht in PACK.DPL aufgenommen. Folglich muß man die Datei RARE.DLL nicht zusammen mit PACK weitergeben. UNIT1 ist aber trotzdem in PACK.DCP enthalten. Wird UNIT1 von einem anderen Package oder einer anderen Anwendung referenziert, das z. B. die PACK nutzt, wird UNIT1 aus PACK.DCP kopiert und direkt in das Projekt compiliert.
Wird nun eine zweite Unit (UNIT2) in PACK eingefügt, die UNIT1 verwendet, fügt der Compiler UNIT1 in PACK.DPL ein, obwohl PACK mit der Direktive {$WEAKPACKAGEUNIT ON} in UNIT1.PAS compiliert wurde. Andere Packages oder Anwendungen, die UNIT1 referenzieren, verwenden weiterhin die Kopie aus PACK.DCP.
Als Konsequenz dürfen Unit-Dateien mit der Direktive {$WEAKPACKAGEUNIT ON} keine globalen Variablen, Initialisierungs- oder Finalisierungsabschnitte enthalten.
Die Direktive $WEAKPACKAGEUNIT wurde von Borland für Entwickler bereitgestellt, die DPLs an andere Delphi-Programmierer weitergeben. Sie führt zur Vermeidung der Distribution selten benötigter DLLs und verhindert Konflikte zwischen Packages, die auf dieselbe externe Bibliothek zugreifen.
Beispielsweise referenziert die Unit PenWin von Delphi PENWIN.DLL. PenWin wird nur in wenigen Projekten verwendet, und auf den meisten Rechnern ist PENWIN.DLL nicht installiert. Aus diesem Grund wurde die Unit PenWin mit der {$WEAKPACKAGEUNIT ON} in VCL30 aufgenommen. Wenn Sie ein Projekt compilieren, das PenWin und das Package VCL30 verwendet, wird PenWin aus VCL30.DCP kopiert und direkt in das Projekt compiliert. Die ausführbare Datei wird statisch mit PENWIN.DLL verknüpft.
Ein anderes Vorgehen würde zu zwei Problemen führen. Erstens würde VCL30 statisch mit PENWIN.DLL verknüpft werden und könnte auf Rechnern ohne PENWIN.DLL nicht geladen werden. Zweitens würde beim Erstellen eines Packages mit PenWin ein Compiler-Fehler ausgelöst, da sich die Unit PenWin sowohl in VCL30 als auch in Ihrem Package befände. PenWin könnte also in Standarddistributionen von VCL30 nicht verwendet werden.
| Direktive $WEAKPACKAGEUNIT | |
Wird das Package von der Befehlszeile aus compiliert, können neue Package-spezifische Schalter verwendet werden, die in der nachfolgenden Tabelle zusammengefaßt sind:
|
Schalter
|
Beschreibung
|
|
-$G-
|
Dieser Schalter verhindert die Erstellung importierter Datenreferenzen. Er verbessert die Effizienz beim Speicherzugriff, verhindert aber die Referenzierung von Variablen anderer Packages. Der Schalter -$G- kann die gemeinsame Nutzung des Packages mit anderen Packages in einer Anwendung verhindern.
|
|
-LEPfad
|
Mit diesem Schalter wird das Verzeichnis für die .DPL-Datei des Package angegeben.
|
|
Schalter
|
Beschreibung
|
|
-LNPfad
|
Mit diesem Schalter wird das Verzeichnis für die DCP-Datei des Packages angegeben.
|
|
-Z
|
Dieser Schalter verhindert das spätere implizite Neucompilieren des Packages.
|
| Befehlszeilen-Com-piler verwenden | |
Zum Erstellen eines Package eine Quelltextdatei mit der Dateinamenerweiterung DPK compiliert. Der Name der .DPK-Datei wird als Name für alle vom Compiler generierten Dateien verwendet.
Die folgende Tabelle beschreibt die Dateien, die vom Compiler im Rahmen der erfolgreichen Compilierung eines Packages erzeugt werden.
|
Dateierweiterung
|
Inhalt
|
|
DCP
|
Ein Binär-Image mit einem Package-Header und allen DCU-Dateien im Package. Für jedes Package wird eine DCP-Datei erzeugt. Der Name der DCP-Datei ist mit dem der DPK-Quelltextdatei identisch.
|
|
DCU
|
Ein Binär-Image für eine im Package enthaltene Unit-Datei. Gegebenenfalls wird für jede Unit-Datei eine DCU-Datei erzeugt.
|
|
DPL
|
Laufzeit-Package. Diese Datei ist eine Windows-DLL mit speziellen Delphi-Merkmalen. Der Name der DPL-Datei ist mit dem der DPK-Quelltextdatei identisch.
|
| Package-Dateien nach erfolgreicher Compilierung
|
|
|