Vor kurzem habe ich an Delphi gearbeitet und festgestellt, dass im Originalprogramm viele Pakete verwendet wurden, aber ich war immer in einem ignoranten Zustand. Es kann einige Zeit dauern, dieses Problem zu untersuchen. Listen Sie also zunächst die Fragen auf, die analysiert werden müssen:
Was ist eine Tasche? Was ist ein Exe? Was sind ihre Kompositionsunterschiede? Wie ist die Beziehung zwischen Paket und DCU? Was macht DCP? Wie ist die Beziehung zwischen diesen Dateien zur Kompilierungszeit? Wie wird es geladen? Wie arbeite ich das Paket nach dem Laden? DLL kann exportieren, aber warum hilft der Delphi nicht, die Exporte des Pakets zu formulieren, aber einige Code verwendet Expros im Paket?
Schauen wir uns zunächst den Zusammenstellungsprozess von Delphi an. Es gibt zwei Arten von Projekten in Delphi: Pakete und Programme. Beginnen Sie mit einem einfachen, beginnen wir mit DPR. Laut Delphis Hilfedokumentation lautet die Struktur einer typischen DVR -Datei wie folgt:
1 Programmredakteur;
2
3 Verwendungen
4 Formulare, {wechseln Sie zu QForms in Linux}
5 Reobout in 'reoBout.pas' {überbox},
6 Bleib in 'reme.pas' {MainForm};
7
8 {$ r *.res}
9
10 Beginnen Sie
11 application.titel: = 'Texteditor';
12 application.createForm (tmainForm, MainForm);
13 Anwendung.Run;
14 Ende.
Unter ihnen, 10 bis 14 Zeilen, beginnen ... Ende ist natürlich der Ausführungseingang des Programms. Der Teil der Verwendung zeigt einige Einheiten an, die das Programm verwenden muss, was ziemlich vage ist. brauchen? Dann verwendet jede Einheit andere Einheiten, und dieses Problem scheint immer komplizierter zu werden. Schauen wir uns zuerst die Struktur des gesamten Quellcodes an:
Ich denke, der erste Schritt des Compilers besteht darin, diesen gerichteten Diagramm zu durchqueren, bei Bedarf jede Einheit zu kompilieren und die entsprechende DCU zu erzeugen. Was dieses "notwendige" Problem betrifft, dachte ich zunächst, dass die Einheitserklärung der Nutzung war, aber später stellte ich fest, dass es falsch war. Da im obigen Fall Unit3 den Pfad in der Verwendung von Einheit1 nicht angibt, wird die entsprechende DCU -Datei jedoch weiterhin korrekt generiert. Später wird Filemon zur Überwachung der Dateiöffnungssituation verwendet, und der Erkennungsvorgang lautet wie folgt: Für jeden Knoten im Diagramm sucht der Compiler die entsprechenden Knoten im Suchpfad im aktuellen Verzeichnis - Projektattribut - Bibliothekspfad in der Bibliothek Umgebung.
Nachdem die Kompilierung abgeschlossen ist, hat jede Einheit (d. H. Die PAS -Datei) die DCU -Datei dafür generiert. Wenn es um Verbindungen geht, ist das Problem kompliziert. Statische Verbindung bedeutet, all diese DCU miteinander zu kombinieren. Auf diese Weise wird der Ruf einer Einheit an eine andere Einheit zu einer internen Angelegenheit des Programms. Dieser Vorteil ist, dass es schnell und einfach ist, und Probleme wie gleichzeitige gemeinsame Nutzung sind leicht zu handhaben. Der Nachteil ist, dass das Zielprogramm groß ist und ein anderes Programm jetzt geschrieben werden soll und Unit3 wiederverwendet werden kann, Unit3.dcu wird bei Verbindung erneut kopiert. Wenn zwei Programme gleichzeitig ausgeführt werden, werden zwei Kopien von Unit3 im Speicher vorhanden sein, was ein Abfall ist. Dynamische Verbindung bedeutet, dass sie bei zwei Programmen nur Verweise auf Unit3 behalten und den Inhalt von Unit3 nicht kopieren. Lasten Sie zur Laufzeit die Einheit3 in den Speicher und machen Sie die beiden Programme gemeinsam. DLL und BPL sind beide Lösungen für dynamische Verbindungen. Das Problem ist, dass die einzige Option für die Verbindung in Delphi im Menü "Paket -Pakete" -Pakete in Delphi angezeigt wird, und der Satz "Erstellen mit Laufzeitpaketen" ist wirklich zu vage. Also müssen wir es noch einmal studieren.
Wenn das Programm ausgeführt wird, können wir die Ansicht | Debugg -Fenster | Moudles verwenden, um zu sehen, welche Dinge in den Speicher geladen werden und welche Inhalte sie enthalten.
Um einfach zu sein, richten wir ein Programm mit der folgenden Struktur ein:
ProgrammprojektExe;
Verwendung
Formen,
Fenster,
UnitFormmain in 'UnitFormmain.pas' {Formmain};
{$ R *.res}
Beginnen
Application.initialize;
Application.createForm (tFormmain, Formmain);
Anwendung.Run;
Ende.
Unitformmain;
Schnittstelle
Verwendung
Windows, STDCtrls, Formulare, UnitFormanother, Klassen, Steuerelemente;
Typ
TFormmain = Klasse (tform)
Button1: Tbutton;
PROCEDURE Taste1Click (Absender: Tobject);
Privat
{Private Deklarationen}
öffentlich
{Öffentliche Erklärungen}
Ende;
var
Formmain: tFormmain;
Durchführung
{$ R *.dfm}
procedure tFormmain.button1click (Absender: tobject);
var
Lform: tformanother;
Beginnen
Lform: = tFormanother.create (Anwendung);
Lform.showmodal;
Lform.free;
Ende;
Ende.
UnitFormanotherother;
Schnittstelle
Verwendung
Formen;
Typ
Tformanother = class (tform)
Privat
{Private Deklarationen}
öffentlich
{Öffentliche Erklärungen}
Ende;
Durchführung
{$ R *.dfm}
Ende.
Lassen Sie uns jetzt die Nachrichten erhalten. "Build With Runtime Pakete" wird überprüft, und jetzt wird festgestellt, dass die Datei Runtime ProjectExe.exe nur vier Teile enthält: zwei Formular, ein sysinit.pas und ein ProjectExe.dpr; Im Prozessbaum: RTL60 und VCL60 sind ihr Inhalt die Einheiten, die gerade in der statischen Verbindung erschienen sind. ProjectExe.exe ist jetzt nur 16K. Mit anderen Worten, ein Teil der Einheit im gerichteten Diagramm wird in der Exe platziert und der andere Teil wird in der BPL platziert. Aber worauf basiert die Abteilung? Basiert es auf der Verwendungsklausel oder auf der Liste in "Build With Runtime Pakete" hier? Wenn ich den Test fortsetze, stellte ich fest, dass die beiden BPL -Plus ein in Speicher geladener EXE weiterhin in den Speicher geladen werden. Die Exe hat sich geändert: Die Anzahl der Einheiten im Inneren hat zugenommen, und sie befinden sich im Grunde im VCL60 -Paket. Ich denke, es sollte eine Anforderungen zwischen RTL- und VCL -Paketen geben. Dies wird im nächsten Schritt getestet. Während des anfänglichen Schätzprozesses wird die Paketliste jedoch definitiv verwendet, um Einheiten auszuschließen, die bereits im Paket von der EXE vorhanden sind.
Nach dynamischer Verbindung gibt es ein weiteres Problem: Laden. Es gibt zwei Strategien zum Laden, statisch, auch als automatisch bezeichnet, was Code von Delphi generiert und das Paket automatisch lädt, bevor das EXE dynamisch ist. es. Das Problem ist, dass ich unter welchen Umständen Delphi ein Paket automatisch laden muss und unter welchen Umständen ich vermeiden kann, dass Delphi intelligent ist, damit ich das Paket flexibel verwenden kann. Im vorherigen Experiment ist nur ersichtlich, dass das statisch verbundene Paket in den Speicher geladen wurde, bevor die DPR -Datei ausgeführt wird. Ich kenne den spezifischen Prozess nicht.