Moduldefinitionsdateien

Aus Appmethod Topics
Wechseln zu: Navigation, Suche

Nach oben zu ILINK32


Moduldefinitionsdateien werden zusammen mit ILINK32 verwendet. Eine Moduldefinitionsdatei ist eine ASCII-Datei, die ILINK32 Aufschluss über den Inhalt und die Systemanforderungen einer Windows-Anwendung gibt. Sie können eine Moduldefinitionsdatei mit IMPDEF erstellen.

Die Moduldefinitionsdatei verzeichnet den Namen der .EXE- oder .DLL-Datei, bestimmt den Typ der Anwendung, führt die importierten und exportierten Funktionen auf, beschreibt die Attribute der Codeabschnitte und Datensegmente, erlaubt die Festlegung von Attributen für weitere Codeabschnitte und Datensegmente, legt die Größe des Stacks fest und ermöglicht das Einfügen eines DOS-Stub-Programms.

CODE-Anweisung

Definiert die Standardattribute von Codeabschnitten. Codeabschnitte können beliebige Namen haben, sie müssen aber zu Abschnittsklassen gehören, deren Namen auf CODE enden (wie etwa CODE oder MEINCODE).

CODE [PRELOAD | LOADONCALL]
      [EXECUTEONLY | EXECUTEREAD]
  • PRELOAD bedeutet, dass der Code gleichzeitig mit dem aufrufenden Programm geladen wird.
  • LOADONCALL (Voreinstellung) bedeutet, der Code wird geladen, wenn er vom Programm aufgerufen wird.
  • EXECUTEONLY bedeutet, ein Codeabschnitt kann nur ausgeführt werden.
  • EXECUTEREAD (Voreinstellung) bedeutet, der Codeabschnitt kann gelesen und ausgeführt werden.
  • FIXED (Voreinstellung) bedeutet, der Abschnitt verbleibt an einer festen Speicherposition.
  • MOVEABLE bedeutet, der Abschnitt ist im Speicher verschiebbar.
  • DISCARDABLE bedeutet, der Abschnitt kann freigegeben werden, wenn er nicht mehr verwendet wird (das impliziert MOVEABLE).
  • NONDISCARDABLE (Voreinstellung) bedeutet, der Abschnitt kann nicht freigegeben werden.

DATA-Anweisung

Definiert die Attribute von Datensegmenten:

DATA [NONE | SINGLE | MULTIPLE]
     [READONLY | READWRITE]
     [PRELOAD | LOADONCALL]
     [SHARED | NONSHARED]
  • NONE bedeutet, es wird kein Datensegment erstellt. Diese Option steht nur für Bibliotheken zur Verfügung.
  • SINGLE (Voreinstellung für DLLs) bedeutet, es wird genau ein Datensegment erstellt und von allen Prozessen gemeinsam genutzt.
  • MULTIPLE (Voreinstellung für .EXE-Dateien) bedeutet, es wird für jeden Prozess ein eigenes Datensegment erstellt.
  • READONLY bedeutet, das Datensegment kann nur gelesen werden.
  • READWRITE (Voreinstellung) bedeutet, das Datensegment kann gelesen und es kann auch in das Datensegment geschrieben werden.
  • PRELOAD bedeutet, das Datensegment wird geladen, wenn ein Modul, das es verwendet, zum ersten Mal geladen wird.
  • LOADONCALL (Voreinstellung) bedeutet, das Datensegment wird beim ersten Zugriff darauf geladen. (LOADONCALL wird bei 32 Bit-Anwendungen ignoriert).
  • SHARED bedeutet, ein Exemplar des Datensegments wird gemeinsam von allen Prozessen genutzt.
  • NONSHARED (Voreinstellung für Programme und DLLs) bedeutet, für jeden Prozess, der es nutzt, wird eine Kopie des Datensegments geladen.

DESCRIPTION-Anweisung (optional)

Fügt Text in das Anwendungsmodul ein; ein typischer Anwendungsfall ist eine Autoren-, Datums- oder Copyright-Angabe:

DESCRIPTION 'Text'

Text ist eine ASCII-Zeichenfolge, die in einfache Anführungszeichen eingeschlossen ist.

EXETYPE-Anweisung

Definiert den Standard-Header-Typ für ausführbare Programme (.EXE). Sie können diesen Abschnitt aus Gründen der Abwärtskompatibilität bei 32 Bit-Anwendungen belassen; falls Sie aber den EXETYPE ändern müssen, finden Sie Informationen dazu unter der Anweisung NAME.

EXETYPE  [WINDOWAPI] | [WINDOWCOMPAT]
  • WINDOWAPI ist ein ausführbares Windows-Programm und entspricht der ILINK32-Option -aa.
  • WINDOWCOMPAT legt eine Windows-kompatible Zeichenmodusanwendung fest. Dieser Befehl entspricht der ILINK32-Option -ap.

EXPORTS-Anweisung

Definiert die Namen und Attribute von Funktionen, die exportiert werden sollen. Das Schlüsselwort EXPORTS bezeichnet den Anfang der Definitionen. Ihm kann eine beliebige Anzahl von Exportdefinitionen folgen, jede in einer eigenen Zeile.

EXPORTS
   <EsportName> [<Ordinal>]
   [RESIDENTNAME] [<Parameter>]
  • <ExportName> gibt einen ASCII-String an, der das zu exportierende Symbol wie folgt definiert:
<EntryName> [=<InternalName>]


<EntryName> ist der extern sichtbare Name, der in der Eintragstabelle der ausführbaren Datei verzeichnet ist.


<InternalName> ist der Name, der innerhalb der Anwendung in Bezug auf diesen Eintrag verwendet wird.
  • <Ordinal> legt den Ordinalwert der Funktion wie folgt fest:
@<ordinal>


<ordinal> ist ein ganzzahliger Wert, der den Ordinalwert der Funktion angibt. Wenn ein Anwendungsmodul oder ein DLL-Modul eine aus einer dynamischen DLL exportierte Funktion aufruft, kann das aufrufende Modul die Funktion entweder über den Namen oder den Ordinalwert aufrufen. Dabei ist der Aufruf über den Ordinalwert schneller, da für das Auffinden der Funktion kein Zeichenvergleich erforderlich ist. Auch hinsichtlich der Speicherbelegung ist das Exportieren einer Funktion (von der DLL dieser Funktion aus gesehen) sowie das Importieren/Aufrufen (vom aufrufenden Modul aus gesehen) über den Ordinalwert effizienter.


Wenn eine Funktion unter Verwendung ihres Ordinalwerts exportiert wird, wird der Name in der nicht residenten Namenstabelle abgelegt. Wird eine Funktion unter Verwendung ihres Namens exportiert, steht der Name in der residenten Namenstabelle. Die residente Namenstabelle für ein Modul ist immer dann im Speicher präsent, wenn das Modul geladen wurde; die nicht residente Namenstabelle befindet sich dagegen nicht im Speicher.
  • RESIDENTNAME legt fest, dass der Funktionsname jederzeit resident sein muss. Das ist nur dann sinnvoll, wenn die Funktion über ihren Ordinalwert exportiert wird (d. h. der Name wäre durch Voreinstellung nicht resident).
  • <Parameter> ist ein ganzzahliger Wert, der die Anzahl der Wörter angibt, die die Funktion bei der Parameterübergabe erwartet. Die Angabe ist optional.

HEAPSIZE-Anweisung

Definiert die Byte-Anzahl, die die Anwendung für ihren lokalen Heap benötigt. Immer, wenn eine Anwendung lokalen Speicher reserviert, verwendet sie dazu den lokalen Heap.

HEAPSIZE <Reserve>[, <Commit>]
  • <Reserve> kann ein dezimaler oder hexadezimaler Wert sein; die Voreinstellung ist 1 MB. Um die Abwärtskompatibilität (16-Bit-Kompatibilität) für 32-Bit-Ports zu vereinfachen, verwendet der Linker den Vorgabewert von 1 MB, wenn in der .DEF-Datei für Reserve ein kleinerer Wert als 64 K angegeben ist.
  • <Commit> ist ein dezimaler oder hexadezimaler Wert. Die Angabe dieses Wertes ist optional, die Voreinstellung beträgt 4 K. Der kleinstmögliche Wert für Commit ist 0. Ferner muss die angegebene oder vorgegebene Größe von Commit immer kleiner als oder maximal gleich groß wie der Wert von Reserve sein.

Reservierter Speicher bezieht sich auf die größtmögliche Speichergröße, die entweder im physikalischen Arbeitsspeicher oder in der Auslagerungsdatei zugewiesen werden kann. Anders gesagt, der Wert von Reserve gibt die maximal mögliche Heap-Größe an. Das Betriebssystem stellt sicher, dass die angegebene Speichermenge reserviert und erforderlichenfalls zugewiesen wird.

Die Bedeutung von gebundenem Speicher (committed memory) unterscheidet sich bei den verschiedenen Betriebssystemen. Unter Windows NT bezeichnet gebundener Speicher die Menge Arbeitsspeicher, die dem Heap zum Zeitpunkt des Ladens bzw. der Initialisierung der Anwendung zugewiesen wird. Gebundener Speicher bedeutet die Zuweisung einer bestimmten Menge Platz im physikalischen Speicher oder in der Auslagerungsdatei. Ein höherer Wert für Commit spart Zeit, wenn die Anwendung mehr Heap-Speicher benötigt, erhöht aber den Speicherbedarf und verlangsamt unter Umständen das Laden der Anwendung.{{f|cmd|

Die in der .DEF-Datei festgelegten Größen für reservierten oder gebundenen Heap können mit den ILINK32-Befehlszeilenoptionen -H oder -Hc überschrieben werden. Mit -H kann auch ein kleinerer Wert für Reserve festgelegt werden als die 64 K, die in der .DEF-Datei mindestens angegeben werden müssen.

IMPORTS-Anweisung

Definiert die Namen und Attribute von Funktionen, die aus DLLs importiert werden sollen. Das Schlüsselwort IMPORTS markiert den Beginn der Definitionen. Ihm kann eine beliebige Anzahl von Importdefinitionen folgen, von denen jede in einer eigenen Zeile stehen muss.

IMPORTS
[<InternalName>=]<ModuleName>.<Entry>
  • <InternalName> ist ein ASCII-String, der den eindeutigen Namen angibt, den die Anwendung zum Aufrufen der Funktion verwendet.
  • <ModuleName> definiert ein oder mehrere ASCII-Zeichen (Großbuchstaben), die den Namen des ausführbaren Moduls festlegen, in dem die Funktion steht. Der Modulname muss dem Namen der ausführbaren Datei entsprechen. So hat die Datei SAMPLE.DLL z. B. den Modulnamen SAMPLE.
  • <Entry> benennt die Funktion, die importiert wird – entweder ein ASCII-String für den Namen der Funktion oder eine Ganzzahl für ihren Ordinalwert.

Statt die importierten DLL-Funktionen in der IMPORTS-Anweisung aufzuführen, kann die Importbibliothek für die DLL in die Projektverwaltung aufgenommen werden.

Sie müssen __declspec(dllimport) oder __import verwenden, um beliebige gewünschte Funktionen, Klassen oder Daten zu importieren. Die vorzuziehende Methode ist __declspec(dllimport).

Das Schlüsselwort IMPORTS kann wie folgt für (globale) Variablen angewendet werden:

[ in the dll source file (dll.cpp) ] int sample = 100;
[ dll.def ]     EXPORTS       _sample
[ in application source file (app.cpp) ]
int _declspec(dllimport) sample;
[ app.def ]
  IMPORTS
    dll._sample

LIBRARY-Anweisung

Definiert den Namen eines DLL-Moduls. Eine Moduldefinitionsdatei kann entweder eine NAME-Anweisung für eine .EXE oder eine LIBRARY-Anweisung für eine .DLL enthalten. Der Namen eines Bibliotheksmoduls muss dem Namen der ausführbaren Datei entsprechen. So hat z. B. die Bibliothek MYLIB.DLL den Modulnamen MYLIB.

LIBRARY <LibrarName> [INITGLOBAL | INITINSTANCE]
  • <LibraryName> (optional) ist ein ASCII-String, der den Namen des Bibliotheksmoduls festlegt. Wenn Sie keinen LibraryName angeben, verwendet ILINK32 den Dateinamen ohne die Dateinamenserweiterung. Wenn die Moduldefinitionsdatei weder eine NAME- noch eine LIBRARY-Anweisung enthält, geht ILINK32 von einer NAME-Anweisung ohne einen ModuleName-Parameter aus.
  • INITGLOBAL bedeutet, dass die Initialisierungsroutine der Bibliothek aufgerufen wird.
  • INITINSTANCE bedeutet, dass die Initialisierungsroutine jedes Mal aufgerufen wird, wenn ein neuer Prozess die Bibliothek verwendet.

NAME-Anweisung

Gibt den Namen des ausführbaren Moduls der Anwendung an. Der Modulname bezeichnet beim Exportieren von Funktionen das Modul. NAME muss vor EXETYPE erscheinen. Wenn NAME und EXETYPE nicht den gleichen Zieltyp angeben, verwendet der Linker den in NAME festgelegten Typ.

NAME <ModuleName> [WINDOWSAPI] | [WINDOWCOMPAT]
  • <ModuleName> (optional) enthält ein oder mehrere ASCII-Zeichen (in Großbuchstaben), die den Namen des ausführbaren Moduls festlegen. Der Name muss dem der ausführbaren Datei entsprechen. So hat z. B. eine Anwendung mit der ausführbaren Datei SAMPLE.EXE den Modulnamen SAMPLE.
Wenn keine Angabe für <ModuleName> gemacht wird, geht ILINK32 davon aus, dass der Modulname dem Namen der ausführbaren Datei entspricht. Wenn beispielsweise der Name der ausführbaren Datei MYAPP.EXE ist und kein Modulname angegeben wurde, geht ILINK32 von dem Modulnamen MYAPP aus. Wenn die Moduldefinitionsdatei weder eine NAME- noch eine LIBRARY-Anweisung enthält, geht ILINK32 von einer NAME-Anweisung ohne einen <ModuleName>-Parameter aus.
  • WINDOWSAPI legt eine ausführbare Windows-Datei fest; dieser Parameter entspricht der ILINK32-Option ‑aa.
  • WINDOWCOMPAT legt eine Windows-kompatible Zeichenmodusanwendung fest. Dieser Befehl entspricht der ILINK32-Option -ap.

SECTIONS-Anweisung

Ermöglicht das Festlegen von Attributen für einen oder mehrere Abschnitte in der Image-Datei. Mit dieser Anweisung können Sie die voreingestellten Attribute für jeden Abschnittstyp überschreiben.

SECTIONS<section_name> [CLASS '<ClassName>'] <attributes>
  • SECTIONS kennzeichnet den Anfang einer Liste von Abschnittsdefinitionen.
  • Nach dem Schlüsselwort SECTIONS muss jede Abschnittsdefinition in einer eigenen Zeile aufgeführt werden. Das Schlüsselwort SECTIONS kann selbst jedoch in der gleichen Zeile wie die erste Definition oder in der vorangehenden Zeile stehen. Ferner kann die .DEF-Datei eine oder mehrere SECTIONS-Anweisungen enthalten. Das Schlüsselwort SEGMENTS wird als Synonym für SECTIONS unterstützt.
  • <ClassName> berücksichtigt die Groß-/Kleinschreibung. Das Schlüsselwort CLASS wird aus Gründen der Kompatibilität unterstützt, wird aber ignoriert.
  • <Attributes> kann einen oder mehrere der folgenden Werte annehmen: EXECUTE, READ, SHARED und WRITE.

SEGMENTS-Anweisung

Definiert die Attribute von zusätzlichen Code- und Datenabschnitten. Das Schlüsselwort SEGMENTS wird als Synonym für SECTIONS unterstützt. Die Syntax lautet:

SEGMENTS
   <SegmentName> [CLASS '<ClassName>']
        [<MinAlloc>]
        [SHARED | NONSHARED]
        [PRELOAD | LOADONCALL]
  • <SegmentName> ist eine Zeichenkette, die das neue Segment benennt. Es können beliebige Namen vergeben werden, einschließlich der Standard-Segmentnamen _TEXT und _DATA, die für die Standard-Code- und -Datensegmente stehen.
  • <ClassName> (optional) ist der Klassenname des angegebenen Segments. Wenn kein Klassenname festgelegt wird, verwendet ILINK32 den Klassennamen CODE.
  • <MinAlloc> (optional) ist ein ganzzahliger Wert, der die minimale Speicherplatzreservierung für das Segment angibt. ILINK32 ignoriert diesen Wert.
  • SHARED bedeutet, dass ein Exemplar des Segments von allen Prozessen gemeinsam genutzt wird.
  • NONSHARED (Voreinstellung für .EXE-Dateien und DLLs) bedeutet, dass für jeden Prozess, der das Datensegment benötigt, eine Kopie des Segments geladen wird.
  • PRELOAD bedeutet, dass das Segment sofort geladen wird.
  • LOADONCALL bedeutet, das Segment wird erst beim Zugriff geladen oder durch einen direkten Aufruf (dies wird von ILINK32 ignoriert). Der Ressourcen-Compiler kann die Option LOADONCALL außer Kraft setzen und Segmente sofort laden.

STACKSIZE-Anweisung

Definiert die Byte-Anzahl, die die Anwendung für ihren lokalen Stack benötigt. Eine Anwendung benötigt den lokalen Stack immer dann, wenn sie Funktionen aufruft.

STACKSIZE <Reserve>[, <Commit>]
  • <Reserve> kann ein dezimaler oder hexadezimaler Wert sein; die Voreinstellung ist 1 MB. Um die Abwärtskompatibilität (16-Bit-Kompatibilität) zu vereinfachen, verwendet der Linker den Vorgabewert von 1 MB, wenn in der .DEF-Datei für Reserve ein kleinerer Wert als 64 K angegeben ist.
  • <Commit> ist ein dezimaler oder hexadezimaler Wert. Die Angabe dieses Wertes ist optional, die Voreinstellung beträgt 8 K. Die Mindestgröße, die für Commit festgelegt werden kann, ist 4 K. Ferner muss der angegebene Wert oder die Voreinstellung für Commit stets kleiner als oder gleich groß wie der Wert von Reserve sein.

Reservierter Speicher bezieht sich auf die größtmögliche Speichergröße, die entweder im physikalischen Arbeitsspeicher oder in der Auslagerungsdatei zugewiesen werden kann. Anders gesagt, der Wert von Reserve gibt die maximal mögliche Stack-Größe an.

Das Betriebssystem stellt sicher, dass die angegebene Speichermenge reserviert und erforderlichenfalls zugewiesen wird.

Die Bedeutung von gebundenem Speicher (committed memory) unterscheidet sich bei den verschiedenen Betriebssystemen. Unter Windows NT bezeichnet gebundener Speicher die Menge Arbeitsspeicher, die dem Stack zum Zeitpunkt des Ladens bzw. der Initialisierung der Anwendung zugewiesen wird. Gebundener Speicher bedeutet die Zuweisung einer bestimmten Menge Platz im physikalischen Speicher oder in der Auslagerungsdatei. Ein höherer Wert für Commit spart Zeit, wenn die Anwendung mehr Stack-Speicher benötigt, erhöht aber den Speicherbedarf und verlangsamt unter Umständen das Laden der Anwendung.{{f|cmd|

Die in der .DEF-Datei festgelegten Größen für reservierten oder gebundenen Stack können mit den ILINK32-Befehlszeilenoptionen -S oder -Sc überschrieben werden. Mit -S kann auch ein kleinerer Wert für Reserve festgelegt werden als die 64 K, die in der .DEF-Datei mindestens angegeben werden müssen.

Hinweis: Verwenden Sie die Anweisung STACKSIZE nicht beim Compilieren von DLLs.

STUB-Anweisung

Fügt eine durch <FileName> festgelegte ausführbare DOS-Datei am Anfang des Moduls ein. Der ausführbare Stub gibt eine Warnung aus und bricht ab, wenn der Benutzer versucht, ihn in einer falschen Umgebung auszuführen (zum Beispiel eine Windows-Anwendung unter DOS).

STUB '<FileName>'
  • <FileName> ist der Name der ausführbaren DOS-Datei, die am Beginn des Moduls eingefügt werden soll. Der Name muss den DOS-Konventionen für Dateinamen entsprechen. Befindet sich die mit FileName festgelegte Datei nicht im aktuellen Verzeichnis, sucht ILINK32 in den Verzeichnissen, die der Benutzer mit der Umgebungsvariable PATH festgelegt hat.

Appmethod C++ fügt einen vordefinierten Stub am Beginn einer Windows-Anwendung ein, sofern kein anderer Stub mit der STUB-Anweisung festgelegt wurde. STUB sollte deshalb nicht verwendet werden, um lediglich die WINSTUB.EXE einzubinden, da dies der Linker automatisch ausführt.

SUBSYSTEM-Anweisung

Ermöglicht die Angabe des Windows-Subsystems und der Subsystem-Versionsnummer für die Anwendung, die gelinkt werden soll.

SUBSYSTEM [<subsystem>,]<subsystemID>
  • <Subsystem> (optional) kann einen der folgenden Werte annehmen: WINDOWS, WINDOWAPI, WINDOWCOMPAT. Wenn Sie keinen Wert für <Subsystem> angeben, geht der Linker von der Voreinstellung für ein WINDOWS-Subsystem aus.
  • <SubsystemID> muss im Format d.d angegeben werden; d ist dabei eine Dezimalzahl. Wenn Sie beispielsweise Windows 4.0 festlegen möchten, können Sie jede der beiden folgenden SUBSYSTEM-Anweisungen verwenden:
SUBSYSTEM 4.0
SUBSYSTEM WINDOWS 4.0

Alle SUBSYSTEM-Anweisungen in einer .DEF-Datei können mit den ILINK32-Befehlszeilenoptionen -a und -V überschrieben werden.

Siehe auch