Ich, ich, meld
In
Unit System.pas gibts eine Struktur PInitContext und eine lokale globale Variable InitContext: TInitContext.
In dieser Struktur gibts ein Member mit Namen InitCount und InitTable. InitCount enthält dabei die Anzahl der zu initialisierenden Units -> Addresse der
Unit Sektion wo initialization und finalization steht. Jede
Unit implementiert so eine Initialisierungs Sektion, egal ob der Programmierer sie im Source der
Unit benutzt oder nicht.
Wir benötigen also den Zugriff auf die Variable InitContext, als erstes. Dazu einmalig irgend ein Program mit MAP Files kompilieren. Im MAP findet sich dann eine Sektion in der alle Variablen, egal ob globale verfügbar oder lokal geschützt, und deren Addressen. Du wählst nun eine globale Variable wie zb. AllocMemSize aus und berechnest zur Variablen InitContext den Addressoffset. Zur Laufzeit kannst du dann mit MyInitContext: PInitContext := PChar(@AllocMemSize) + Offset(InitContext - AllocMemSize) darauf zugreifen. Wir haben also die Speicheraddresse relativ zu einer globalen und fixen Addresse eine Variable ausgerechnet.
Nun können wir auf InitContext und deren Member zugreifen, im speziellen auf InitCount und InitTable. Über InitCount haben wir die Anzahl aller zu Initialisierenden Module, eg. Packages, und zu jedem dieser Packages/Module eine Tabelle mit den Adresszeigern auf die Units. DAS IST die exakte Reihenfolge wie auch die
RTL alle Units initialisiert, also die reale Abhängigkeiten der Packages und Units.
Wir wandeln wir nun diese Zeiger in Namen der Packages und Units um ?
Die Packages sind sehr einfach: mit Module := FinHInstance(InitContext.InitTable[x]) erstmal das Modulhandle des Modules in dem sich die Units finden ermittelt. Dann mit GetModuleFileName(Module, ...) den Namen des Modules/Packages ermittelt.
Die Unitnamen sind da schon schwieriger. Eine Möglichkeit bietet die
RTTI selber und mit Hilfe meiner EnumTypeInfo() Funktion (hier in der CodeLib) kann man alle
RTTI zum ModuleHandle durch iterieren. Interessant sind dabei RTTIs wie Classen etc. pp. die nämlich selber intern den Unitnamen in denen sie implementiert wurden enthalten. Wir müssen nun nur noch die Zeiger die wir über die InitTable auf die
Unit Initialization Addressen erhalten haben mit den Zeigern auf die
RTTI dieser Units synchronisieren.
Eine andere Möglichkeit bieten die Packages und deren Resourcen selber. Ein Module enthält immer zwei Resourcen: PACKAGEINFO und DVCAL. PackageInfo enthält die Namen aller Units. Das dürfte die gleiche Reihenfolge sein wie ind der InitTable (aber nochmal testen).
Auf alle Fälle kommt man so an alle geladenen Module, alle Units ind den Modulen und alle deklarierten Datentypen der
RTTI dynamisch zur Laufzeit des Programmes heran.
Gruß Hagen