DE69414387T2 - Objektorientiertes dynamisches "link"-system, welches auf katalogisierte funktionen und klassen zugreift - Google Patents
Objektorientiertes dynamisches "link"-system, welches auf katalogisierte funktionen und klassen zugreiftInfo
- Publication number
- DE69414387T2 DE69414387T2 DE69414387T DE69414387T DE69414387T2 DE 69414387 T2 DE69414387 T2 DE 69414387T2 DE 69414387 T DE69414387 T DE 69414387T DE 69414387 T DE69414387 T DE 69414387T DE 69414387 T2 DE69414387 T2 DE 69414387T2
- Authority
- DE
- Germany
- Prior art keywords
- function
- library
- class
- record
- link
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Expired - Lifetime
Links
- 230000006870 function Effects 0.000 claims description 435
- 230000004044 response Effects 0.000 claims description 28
- 239000012634 fragment Substances 0.000 description 84
- 238000000034 method Methods 0.000 description 47
- 238000004422 calculation algorithm Methods 0.000 description 21
- 230000003068 static effect Effects 0.000 description 16
- 230000007246 mechanism Effects 0.000 description 9
- 230000036316 preload Effects 0.000 description 9
- 230000008859 change Effects 0.000 description 4
- 238000006243 chemical reaction Methods 0.000 description 4
- 230000008676 import Effects 0.000 description 4
- 230000001419 dependent effect Effects 0.000 description 3
- 238000011161 development Methods 0.000 description 3
- 238000004891 communication Methods 0.000 description 2
- 238000009434 installation Methods 0.000 description 2
- 230000008569 process Effects 0.000 description 2
- 238000012545 processing Methods 0.000 description 2
- 230000006399 behavior Effects 0.000 description 1
- 238000004364 calculation method Methods 0.000 description 1
- 238000010276 construction Methods 0.000 description 1
- 238000012937 correction Methods 0.000 description 1
- 230000003111 delayed effect Effects 0.000 description 1
- 238000013461 design Methods 0.000 description 1
- 238000010586 diagram Methods 0.000 description 1
- 230000007774 longterm Effects 0.000 description 1
- 230000008520 organization Effects 0.000 description 1
- 238000012856 packing Methods 0.000 description 1
- 238000012552 review Methods 0.000 description 1
- 238000007619 statistical method Methods 0.000 description 1
- 238000012795 verification Methods 0.000 description 1
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/44—Arrangements for executing specific programs
- G06F9/445—Program loading or initiating
- G06F9/44521—Dynamic linking or loading; Link editing at or after load time, e.g. Java class loading
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/44—Arrangements for executing specific programs
- G06F9/448—Execution paradigms, e.g. implementations of programming paradigms
- G06F9/4488—Object-oriented
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/44—Arrangements for executing specific programs
- G06F9/445—Program loading or initiating
- G06F9/44536—Selecting among different versions
Landscapes
- Engineering & Computer Science (AREA)
- Software Systems (AREA)
- Theoretical Computer Science (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Stored Programmes (AREA)
- Information Retrieval, Db Structures And Fs Structures Therefor (AREA)
- Computer And Data Communications (AREA)
Description
- Die Erfindung betrifft dynamisches Verknüpfen bzw. Linken von Client-Anwendungen mit Funktionssätzen oder Klassen, die von den Client-Anwendungen verwendet werden, und insbesondere Systeme zum dynamischen Verknüpfen einer Client-Anwendung zur Laufzeit mit Bibliotheken von Funktionssätzen oder Klassen, die entweder vor oder während der Ausführung der Client- Anwendung registriert werden.
- Herkömmlicherweise werden Anwendungsquelldateien zu Objektmodulen kompiliert und dann mit anderen Objektmodulen verknüpft bzw. gelinkt, die im allgemeinen als Bibliotheken bezeichnet werden, um eine vollständige selbständige Anwendung zu bilden. Dies wird als statisches Verknüpfen bzw. Linken bezeichnet. Ein Nachteil des statischen Verknüpfens besteht darin, daß jede Anwendung, die mit der gleichen Bibliotheksroutine verknüpft wird, ihre eigene private Kopie der Routine hat. Der größte Teil des Umfangs der Anwendungen besteht aus Bibliothekscode, der mit jeder Anwendung verknüpft ist. Ein weiterer Nachteil der statischen Verknüpfung besteht darin, daß die Funktionalität, die die Anwendung aus der Bibliothek bezieht, festgelegt ist. Wenn die Bibliothek einen Fehler hat, muß die Anwendung mit der neuen Bibliothek neu verknüpft werden, um den Fehler zu beseitigen.
- Dynamisches Verknüpfen, das mitunter auch als spätes Binden bezeichnet wird, ist anders, da der Anwendungscode und der Bibliothekscode erst dann zusammengebracht werden, wenn die Anwendung angelaufen ist. Wenn der in der Bibliothek befindliche Code erst geladen wird, wenn er tatsächlich gebraucht wird, dann wird dies als dynamisches Laden bezeichnet.
- Wenn die gleiche Bibliothekscodekopie, die von einer Anwendung verwendet wird, auch von anderen Anwendungen zur gleichen Zeit verwendet werden kann, dann wird die Bibliothek als gemeinsame bzw. Gemeinschaftsbibliothek bezeichnet.
- Dynamisches Verknüpfen einer Klasse oder eines Funktionssatzes umfaßt das Binden bzw. Anbinden von Code ("Client- Anwendung"), der eine Klasse oder einen Funktionssatz verwendet, an den Code, der die Klasse oder den Funktionssatz zur Laufzeit implementiert. Der Begriff "dynamisch" bedeutet in diesem Kontext "zur Laufzeit auftretend". Verknüpfen umfaßt sowohl ein Laden des Codes als auch ein Binden wichtiger Verweise zu exportierten Implementationen der Klassen oder Funktionssätze. Viele bestehende dynamische Verknüpfungssysteme führen keine dynamische Verknüpfung auf Klassenebene oder Funktionssatzebene durch. Statt dessen erfolgt die Verknüpfung auf der Ebene der einzelnen Funktionen, die von einer Bibliothek exportiert und von einem Client importiert werden können. Jede einzelne Funktion muß jedoch von der Bibliothek exportiert werden, und jede vom Client verwendete Funktion muß bei diesen bekannten Systemen importiert werden. Um die Sache zu komplizieren, ist der Name der Funktionen nach der Kompilation nicht gleich dem Namen der gleichen Funktionen im Quellcode (d. h. C++). Der Entwickler muß sich also mit sogenannten "verstümmelten" Namen befassen, um die Parameter der bekannten dynamischen Verknüpfungssysteme zu erfüllen.
- Neben weiteren Beschränkungen bewirken bekannte Bindesysteme auf Einzelfunktionsebene, daß die Implementation eines Clients von einem bestimmten Satz von Klassen, der zur Aufbauzeit bekannt ist, abhängig ist. Neue abgeleitete Klassen können somit später nicht hinzugefügt werden, ohne daß der Client neu aufgebaut werden muß. Ferner ermöglichen bekannte dynamische Verknüpfungssysteme keine dynamische Installation des Verküpfungssystems selbst. In bestimmten Fällen muß, nachdem ein neues Verknüpfungssystem installiert ist, das Hostsystem einer neuen Urladung unterzogen werden oder zumindest die Client-Anwendung neu gestartet werden.
- Bestehende dynamische Verknüpfungssysteme sind geeignet, prozedurale Programmiersprachen zu unterstützen, und führen keine objektorientierte dynamische Verknüpfung durch. Da bestimmte objektorientierte Sprachen Derivate von prozeduralen Sprachen (C++ ist z. B. ein Derivat von C) sind, können diese Systeme mitunter dynamische Verknüpfung einer objektorientierten Sprache durchführen, wenn der Programmierer sich in einem unangenehmen Verfahren, nämlich der expliziten Nennung aller Elemente der Klasse, mit einer Klasse befaßt. Dennoch unterstützen diese Systeme objektorientierte Programmiersprachen nicht direkt.
- Demzufolge ist es erwünscht, ein dynamisches Verknüpfungssystem zu objektorientierten Programmiersystemen zu optimieren, die dynamisches Binden auf Klassenebene oder Funktionssatzebene umfassen. Ferner sollte ein solches System stabil sein und dabei eine effiziente Verwendung des internen Speichers und die Versionsbildung von Funktionssätzen oder Klassen unterstützen. Schließlich ist es erwünscht, eine dynamische Registrierung von aktualisierten oder neuen Bibliotheken durchzuführen, so daß eine Client-Anwendung nicht neu gestartet werden muß, um neue Versionen ihrer Bibliotheken zu nutzen.
- EP-A-0 546 684 beschreibt ein System, das es einer Anwendung, die geeignet ist, statische Verfahrensaufrufe zu verwenden, erlaubt, Objekte zu manipulieren, deren Verfahren nur über dynamische Aufrufe verfügbar sind, ohne das Binärbild der Anwendung zu modifizieren. GB-A-2 242 293 beschreibt eine Vorrichtung zur dynamischen (Ausführungszeit-)Verknüpfung von objektorientierten Softwarekomponenten.
- Erfindungsgemäß wird eine Vorrichtung zum Verwalten von Codebetriebsmitteln zur Verwendung durch Client-Anwendungen in einem Computer bereitgestellt, wobei der Computer einen internen Speicher hat, der mindestens eine Client-Anwendung speichert, mit: einem Betriebsmittelsatzkatalog, der im internen Speicher gespeichert ist, wobei der Betriebsmittelsatzkatalog mehrere Funktionssätze von Elementfunktionen durch entsprechende Funktionssatz-IDs identifiziert und Satzdatensätze speichert, die Elementfunktionen in entsprechenden Sätzen kennzeichnen; einer Zuteilmaschine im internen Speicher, die mit einer Client-Anwendung verknüpft ist, um einen bestimmten Funktionssatz-ID zu liefern, als Antwort auf einen Aufruf, durch die Client-Anwendung, einer bestimmten Elementfunktion, die ein Element eines entsprechenden Funktionssatzes ist, der durch den bestimmten Funktionssatz-ID identifiziert wird einer Nachschlag- bzw. Suchmaschine im internen Speicher, die mit dem Betriebsmittelsatzkatalog und der Zuteilmaschine gekoppelt ist und auf den bestimmten Funktionssatz-ID anspricht, um einen Satzdatensatz für den entsprechenden Funktionssatz im Betriebsmittelsatzkatalog nachzuschlagen; und einer Verknüpfungsmaschine im internen Speicher, die mit der Zuteilmaschine gekoppelt ist, um die bestimmte Elementfunktion an die Client-Anwendung als Antwort auf den Satzdatensatz zurückzugeben.
- Die Erfindung leistet explizite Unterstützung für objektorientierte Sprachen, z. B. C++, MCL und Dylan. Diese Unterstützung schließt eine Verknüpfung über die Klasse oder den Klassenbezeichner ein, wobei eine Bibliothek eine Klasse exportiert und ein Client eine Klasse importiert. Der Client hat Zugriff auf alle öffentlichen virtuellen und nichtvirtuellen Elementfunktionen solcher dynamisch verknüpfter Klassen. Der Client kann auch ein Objekt einer Klasse, die zur Kompilierzeit nicht bekannt war, exemplifizieren bzw. als generierte Funktion ableiten. In diesem Fall kann der Client öffentliche virtuelle Elementfunktionen unter Verwendung einer bekannten Schnittstelle einer der Vaterklassen einer Klasse aufrufen.
- Das erfindungsgemäße System verwendet einen dynamischen Funktionssatzkatalog, der direkt oder indirekt vom Client abgefragt werden kann. Da die Implementation einer Klasse letztlich ein Satz von Funktionen ist, können Klassen dynamisch verknüpft werden. Der dynamische Funktionssatz- oder Klassenkatalog wird aus einem Katalogbetriebsmittel aktualisiert, wenn eine Bibliothek registriert wird und wenn eine Registrie rung der Bibliothek beim System rückgängig gemacht wird. Jeder registrierte Funktionssatz oder jede registrierte Klasse erhält bei der Registrierung einen Bezeichner.
- Das System ist besonders geeignet für objektorientierte Programmierumgebungen, wobei für einen Funktionssatz, der eine Klasse kennzeichnet, durch eine direkte Katalogabfrage durch einen Client für einen gegebenen Bezeichner und die entsprechende Information im Katalog bestimmt werden kann, (1) ob die Klasse verfügbar ist, (2) die Klassen-IDs ihrer Vaterklassen, (3) die Klassen-IDs ihrer abgeleiteten Klassen und (4) ob die Klasse durch den Klassen-ID dynamisch instanziert bzw. konkretisiert werden kann. Diese Funktionen ermöglichen es, daß Clients die Verfügbarkeit und Kompatibilität von Klassen dynamisch bestimmen, und ermöglichen es, daß neue Funktionalität in Form von neuen Gemeinschaftsklassenbibliotheken geliefert und einem Client hinzugefügt werden, ohne den Client neu zu kompilieren. Da der gesamte Code, der eine Klasse implementiert, dynamisch verknüpft werden kann, ist der Client nicht von der Implementation des Bibliothekscodes abhängig. Eine Bibliothek kann festgelegt oder erweitert werden, ohne daß der Client oder andere Bibliotheken neu aufgebaut werden müssen. Dies vereinfacht die Entwicklung und Verteilung von Festlegungen und Erweiterungen und ist im allgemeinen besser als bestehende Korrekturmechanismen. Da andere dynamische Verknüpfungssysteme Klassen nicht als unterscheidbare Entität auffassen, existiert das Konzept der Klassenidentifizierung und der Klassenkatalogverwaltung in diesen Systemen nicht.
- Demzufolge kann die Erfindung als System zur Verwaltung von Codebetriebsmitteln zur Verwendung durch Client- Anwendungen in einem Computer beschrieben werden, wobei der Computer einen internen Speicher hat, der mindestens eine Client-Anwendung speichert. Die Vorrichtung weist einen Betriebsmittelsatzkatalog auf, der im internen Speicher gespeichert ist. Der Betriebsmittelsatzkatalog identifiziert mehrere Funktionssätze durch entsprechende Funktionssatz-IDs. Ferner weist der Betriebsmittelsatzkatalog Satzdatensätze auf, die die Implementation von Funktionen innerhalb der entsprechenden Sätze kennzeichnen.
- Eine Zuteilmaschine im internen Speicher, die mit einer Client-Anwendung verknüpft ist, liefert einen bestimmten Funktionssatz-ID als Antwort auf einen Aufruf, durch die Client- Anwendung, einer bestimmten Funktion, die ein Element eines Funktionssatzes ist, der durch den bestimmten Funktionssatz-ID identifiziert wird. Eine Nachschlag- bzw. Suchmaschine im internen Speicher, die mit dem Betriebsmittelsatzkatalog und der Zuteilmaschine gekoppelt ist, spricht auf den bestimmten Funktionssatz-ID an, um einen Satzdatensatz für einen entsprechenden Funktionssatz im Betriebsmittelsatzkatalog zu suchen. Schließlich gibt eine Verknüpfungsmaschine im internen Speicher, die mit der Zuteilmaschine gekoppelt ist, die bestimmte Funktion an die Client-Anwendung zurück, als Antwort auf den Satzdatensatz. Da die Verknüpfungsmaschine auf den Satzdatensatz anspricht, der nicht mit dem Client verknüpft ist, braucht der Client somit nicht die Änderungen in der Struktur der Bibliothek zu kennen, in der der bestimmte Funktionssatz liegt. Der Funktionssatz kann also in den und aus dem internen Speicher verschoben, überarbeitet, in verschiedenen Teilen des internen Speichers abgelegt und anderweitig unabhängig vom Client behandelt werden, ohne daß eine neu Kompilierung der Client-Anwendung erforderlich ist.
- Der Betriebsmittelsatzkatalog ist dadurch gekennzeichnet, daß er Satzdatensätze für Funktionssätze enthält, wobei eine Klasse für ein objektorientiertes System ein Funktionssatztyp ist. Wo der Begriff "Funktionssatz" in den Ansprüchen verwendet wird, ist also gemeint, daß eine Funktionssatzspezies eine Klasse sein kann.
- Unter einem Aspekt der Erfindung weist die Zuteilmaschine einen Zuteildatensatz auf, der mit dem Client verknüpft ist, und speichert einen bestimmten Funktionssatz-ID, der einem Funktionssatz entspricht, dessen aufgerufene Funktion ein Element ist. Außerdem ist eine Zuteilroutine in der Zuteilmaschine vorhanden, die mit dem Zuteildatensatz und der Nachschlagmaschine verknüpft ist und auf den Aufruf an die bestimmte Funktion anspricht, um den bestimmten Funktionssatz-ID an die Nachschlagmaschine zu liefern. In einer bevorzugten Ausführungsform weist die Zuteilroutine ein Zuteilsegment ei ner ersten Ebene auf, das mit dem Client und einer globalen Variablen im internen Speicher verknüpft ist, und ein Zuteilsegment einer zweiten Ebene auf, das mit der globalen Variablen und der Suchmaschine verknüpft ist.
- Unter noch einem weiteren Aspekt der Erfindung weist der Zuteildatensatz einen Funktionsverknüpfungscachespeicher und einen Satzverknüpfungscachespeicher auf. Der Funktionsverknüpfungscachespeicher speichert einen Verknüpfungszeiger zu einer bestimmten Funktion, die von der Verknüpfungsmaschine geliefert wird, als Antwort auf die Rückgabe der bestimmten Funktion an den Client. Die Zuteilmaschine weist eine Routine auf, die im Funktionsverknüpfungscachespeicher einen cachegespeicherten Verknüpfungszeiger zu der bestimmten Funktion sucht und als Antwort auf den cachegespeicherten Verknüpfungsanzeiger, falls vorhanden, zu der bestimmten Funktion springt.
- Der Satzverknüpfungscachespeicher speichert einen Verknüpfungszeiger zum Satzdatensatz für den Satz von Funktionen, einschließlich der bestimmten Funktion, die vom Client bereits aufgerufen worden ist. Die Verknüpfungsmaschine weist eine Routine auf, die den Verknüpfungszeiger an den Satzverknüpfungscachespeicher liefert, als Antwort auf die Rückgabe einer bestimmten Funktion an den Client. Die Zuteilmaschine weist eine Routine auf, die im Satzverknüpfungscachespeicher einen cachegespeicherten Verknüpfungszeiger zum Satzdatensatz sucht und den Satzdatensatz an die Verknüpfungsmaschine zurückgibt, als Antwort auf den cachegespeicherten Verknüpfungszeiger nach einem Aufruf an eine Funktion, die ein Element des Funktionssatzes ist.
- Ein Funktionsaufruf kann also schnell ausgeführt werden, wenn der Funktionsverknüpfungscachespeicher voll ist, und zwar mit einem mittleren Geschwindigkeitsniveau, wenn der Satzverknüpfungscachespeicher voll ist, und langsamer, wenn eine Katalogsuche notwendig ist, um die Funktionsimplementation zu binden.
- Die Erfindung sorgt ferner für eine Zuordnung von Versionsnummern zu Funktionssätzen gemäß einem Standardprotokoll. Der Zuteildatensatz weist unter diesem Aspekt Versionsinformation auf, die mit dem Client verknüpft ist und eine niedrigste Versionsnummer anzeigt, die vom Client für den Funktionssatz unterstützt wird, von dem die bestimmte Funktion ein Element ist. Der Satzdatensatz weist eine Versionsnummer für den entsprechenden Funktionssatz auf. Die Verknüpfungsmaschine weist unter diesem Aspekt eine Routine auf, die auf die Versionsinformation im Zuteildatensatz und die Versionsnummer im Satzdatensatz anspricht, um sicherzustellen, daß der Client eine Version der bestimmten Funktion im Funktionssatz unterstützt.
- Zusätzlich werden den Funktionssätzen laufende Nummern zugeordnet, wenn sie in den internen Speicher geladen werden. Der Zuteildatensatz weist ferner eine laufende Nummer auf, die mit dem Client verknüpft ist und eine laufende Nummer des entsprechenden Funktionssatzes anzeigt, wenn der Satzverknüpfungscachespeicher gefüllt ist. Der Satzverknüpfungscachespeicher speichert einen Zeiger zu einer Verknüpfungsstruktur im internen Speicher, und die Verknüpfungsstruktur weist einen Zeiger zu dem Satzdatensatz mit dem bestimmten Funktionssatz- ID auf. Der Satzdatensatz speichert eine zugeordnete laufende Nummer für den Funktionssatz, wenn er in den internen Speicher geladen wird. Die Verknüpfungsmaschine weist auf: eine Routine, die auf die laufende Nummer im Satzdatensatz und die laufende Nummer im Zuteildatensatz anspricht, um die Gültigkeit des Satzverknüpfungscachespeichereintrags sicherzustellen, und eine Routine zum Löschen der Verknüpfungsstruktur, wenn der entsprechende Funktionssatz geladen ist.
- Die Erfindung sorgt ferner für einen Verwendungszählungsdatensatz im Satzdatensatz. Die Verknüpfungsmaschine weist unter diesem Aspekt eine Routine auf, um die Verwendungszählung zu inkrementieren, wenn eine Client-Anwendung mit dem Funktionssatz entsprechend dem Satzdatensatz gebunden wird, und die Verwendungszählung zu dekrementieren, wenn eine Client-Anwendung den Funktionsdatensatz, der dem Satzdatensatz entspricht, entläßt. Wenn der Funktionssatz eine Klasse kennzeichnet, wird die Verwendungszählung inkrementiert, wenn ein Konstruktor für die Klasse aufgerufen wird, und dekrementiert, wenn ein Destruktor für die Klasse aufgerufen wird. Mit der Verwendungszählung kann also das Speicherverwaltungssystem Funktionssätze entladen, die gegenwärtig nicht von irgendeiner aktiven Anwendung verwendet werden.
- Da ein Client alle abgeleiteten Klassen einer gegebenen Klasse durch den Klassen-ID spezifizieren kann, kann er bestimmen, welche Klassen dynamisch verfügbar sind. Der Satz der verfügbaren Klassen kann zur Laufzeit erweitert werden, wenn neue Bibliotheken registriert werden, und ein Client kann eine Klasse auch dann instanzieren, wenn sie dem System hinzugefügt worden ist, nachdem der Client angelaufen ist. Neue Klassen können in ein Bibliotheksverzeichnis oder einen Ordner im Dateisystem zu jeder Zeit kopiert und automatisch registriert werden, oder ein neuer Ordner oder eine neue Datei kann als Bibliothekscontainer von einem Client explizit registriert werden.
- Dynamische Registrierung von Bibliothek von Funktionssätzen oder Klassen erfolgt mit dem Klassenkatalog. Da der Klassenkatalog nicht mit Clients verbunden ist, müssen lediglich die entsprechenden Datensätze in den Klassenkatalog geschrieben werden, um eine neue Bibliothek zu registrieren.
- Wenn die entsprechenden Datensätze in den Klassenkatalog geschrieben sind, wird die neue Bibliothek für den neuen Client verfügbar. Die oben ausgeführten Prozeduren sind vorhanden, um den Client davor zu schützen, eine Version einer Klasse oder eines Funktionssatzes zu verwenden, die er nicht unterstützt, und um eine nichtgeladene oder erneut geladene Version einer bestimmten Funktion zu finden, die er bereits verwendet hat.
- Die Erfindung ermöglicht ferner die Sicherstellung von Typsicherheit der dynamisch verknüpften Klassen und Funktionssätze mittels Gemeinschaftsbibliotheksfunktionen, die spezifisch geeignet sind, den Klassenkatalog auszunutzen, um diese Sicherheit sicherzustellen. Die bestimmten Funktionen weisen die neue Objektfunktion auf, mit der eine Client-Anwendung Information erwerben kann, die benötigt wird, um ein neues Objekt unter Verwendung des Gemeinschaftsbibliotheksmanagers aufzubauen, und zwar mit Verweis auf den Klassen-ID des neuen Objekts. Unter Verwendung des Klassen-ID sucht der Bibliotheksmanager die Information über die Klasse im Klassenkatalog und gibt einen Konstruktor für die Klasse an den Client zurück. Der Client kann dann den Konstruktor aufrufen, auch wenn er zu der Zeit von der Klasse nicht wüßte, daß sie geschrieben oder kompiliert wurde.
- Außerdem stellt der Bibliotheksmanager eine Klassenüberprüfungsroutine bereit, mit der eine Client-Anwendung den Vater einer bestimmten abgeleiteten Klasse auf Typsicherheit überprüfen kann. Schließlich wird eine Objektkonvertierungsroutine bereitgestellt, mit der ein Client eine Instanz bzw. ein konkreteres Objekt eines bestimmten Objekts als Vaterklassenobjekt konvertieren kann. Diese Routine verwendet den Klassenkatalog, um Distanzen innerhalb des bestimmten Objekts zu den Elementen des Vaters zurückzugeben, obwohl die Client- Anwendung möglicherweise die Struktur des Vaters zu der Zeit, als er geschrieben oder kompiliert wurde, nicht gekannt hat.
- Daraus kann man ersehen, daß die Erfindung einen dynamischen Klassenkatalog bereitstellt, der bei einem gegebenen Klassen-ID abgefragt werden kann, um folgendes zu bestimmen: ob die Klasse verfügbar ist, die Klassen-IDs der Vaterklasse oder -klassen, der Klassen-ID oder die Klassen-IDs der abgeleiteten Klasse oder Klassen und ob die Klasse durch den Klassen-ID dynamisch instanziert werden kann. Wenn ein Objekt instanziert wird, werden die Bibliothek oder Bibliotheken, die die Klasse und ihre Vaterklassen implementiert bzw. implementieren, dynamisch geladen. Ein Objekt kann von einem Client instanziert werden, der zur Kompilierzeit keine Kenntnis von der Klasse des Objekts hatte. Wenn ein solcher Client mit der Schnittstelle einer Vaterklasse des Objekts kompiliert wurde, dann kann das Objekt verwendet werden, als ob es eine Instanz der Vaterklasse wäre.
- Das System ist insbesondere für objektorientierte dynamische Verknüpfung geeignet, die dynamische Bibliotheksregistrierung, dynamische Vererbung und bedarfsweise typsichere dynamische Instanzierung von Objekten durch einen Klassenbezeichner ermöglicht.
- Andere Aspekte und Vorteile der Erfindung erkennt man bei Betrachtung der Figuren der ausführlichen Beschreibung und der beigefügten Ansprüche.
- Fig. 1 ist eine schematische Darstellung eines Computersystems, das den erfindungsgemäßen Gemeinschaftsbibliotheksmanager implementiert.
- Fig. 2 ist eine schematische Darstellung des erfindungsgemäß verwendeten Betriebsmittelsatzkatalogs.
- Fig. 3 ist eine Darstellung der Datenstrukturen, die beim erfindungsgemäßen dynamischen Binden auftreten.
- Fig. 4A bis Fig. 4C stellen die "C"-Sprachdefinition des Fragmentdatensatzes, des Client-VTable-Datensatzes und der Klassen-VTable-Datensätze gemäß einer bevorzugten Ausführungsform dar.
- Fig. 5A bis 5B stellen ein Flußdiagramm für die grundlegende Zuteilarchitektur dar, die bei dem erfindungsgemäßen Gemeinschaftsbibliotheksmanager verwendet wird.
- Fig. 6A, 6B und 6C stellen ein Flußdiagramm für den Schritt 'Klassen-VTable-Datensatz holen' 112 in Fig. 5B dar.
- Fig. 7 ist eine schematische Darstellung der Bibliotheksregistrierfunktion und Organisation.
- Fig. 8 ist ein Flußdiagranm, das den Betrieb der dynamischen Registrierroutine unter Verwendung der Struktur in Fig. 7 zeigt.
- Fig. 9A und 9B zeigen eine neue Objektroutine, die vom Gemeinschaftsbibliotheksmanager ausgeführt wird.
- Fig. 10 zeigt eine Variante der neuen Objektroutine, die verwendet wird, wenn Typsicherheit überprüft werden soll.
- Fig. 11 ist ein Flußdiagramm für eine Klassenüberprüfungsroutine, die vom Gemeinschaftsbibliotheksmanager ausgeführt wird.
- Fig. 12 ist ein Flußdiagramm für eine Objektkonvertierungsroutine, die vom Gemeinschaftsbibliotheksmanager ausgeführt wird.
- Eine ausführliche Beschreibung der bevorzugten Ausführungsformen der Erfindung erfolgt mit Bezug auf die Figuren.
- Fig. 1 bis 12 stellen eine allgemeine Übersicht darüber dar, wie die verschiedenen Aspekte der Erfindung möglich werden. Eine ausführliche Beschreibung mit Verweisungen auf Segmente des Quellcodes folgt auf eine Beschreibung der Figuren.
- Fig. 1 zeigt ein Computersystem, in das die Erfindung aufgenommen worden ist. Das Computersystem weist eine Host-CPU 10 auf, die mehrere Register 11 aufweist, die während der Ausführung von Programmen verwendet werden. Die CPU ist mit einem Bus 12 gekoppelt. Der Bus steht in Verbindung mit einer Eingabevorrichtung 13 und einer Anzeige 14 in dem typischen Computersystem. Ferner ist ein nichtflüchtiger Speicher 15 mit dem Bus 12 gekoppelt. Der nichtflüchtige Speicher enthält große Mengen von Daten und Programmen, z. H. Bibliotheken, Client- Anwendungen und dgl. Ein Hochgeschwindigkeitsspeicher 16 ist mit dem Bus 12 sowohl für Daten als auch für Anweisungen gekoppelt. Der Hochgeschwindigkeitsspeicher speichert mindestens eine Client-Anwendung 17, einen Gemeinschaftsbibliotheksmanager 18, Gemeinschaftsbibliotheksmanager-Globalvariable in einem vorbestimmten Adreßraum innerhalb des Speichers 16, exportierte Bibliotheken 20 und andere Information, wie bekannt.
- Wenn eine Client-Anwendung erfindungsgemäß kompiliert wird, ist eine Anzahl von Einzelheiten in der Anwendung vorgesehen. Diese Einzelheiten sind ein Fragmentdatensatz, ein Fragmentcode, eine Bibliotheksmanagerschnittstelle, ein Client-VTable-Datensatz und eine Zuteilrautine einer ersten Ebene. Der Gemeinschaftsbibliotheksmanager weist eine Bibliotheksaufbauroutine, einen Betriebsmittelsatzkatalog, eine Zuteilroutine einer zweiten Ebene, Klassen-VTable-Datensätze für registrierte Bibliotheken, eine Suchfunktion und eine Verknüpfungsfunktion auf.
- Wie bereits erwähnt, stellt der Betriebsmittelsatzkatalog Information für Funktionssätze oder Klassen bereit, die für einen Client verfügbar sind. Der Fragmentdatensatz zeigt auf den Client-VTable-Datensatz im Client. Die Zuteilroutine der ersten Ebene verwendet im Client-VTable-Datensatz befindliche Information, um die Zuteilroutine der zweiten Ebene aufzurufen. Die Zuteilroutine der zweiten Ebene ruft die Suchfunktion auf, um Information über die aufgerufene Funktion im Betriebsmittelsatzkatalog zu finden. Diese Information wird an eine Verknüpfungsmaschine in Form eines Klassen-VTable- Datensatzes geliefert, der den Client mit der bestimmten Funktion verknüpft, die er aufgerufen hat. Ein bestimmtes Protokoll zur Verwendung dieser Merkmale des Clients und des Gemeinschaftsbibliotheksmanagers werden nachstehend mit Bezug auf Fig. 5 und 6 beschrieben.
- Die Implementation des Betriebsmittelsatzkatalogs, der hier auch als Klassenkatalog bezeichnet wird, ist in Fig. 2 dargestellt. Ein Klassenkatalog ist ein Datensatz 30, der ein erstes Feld 31 aufweist, das eine Zahl speichert, die die Zahl der exportierten Klassen in allen Bibliotheksdateien anzeigt, die beim Katalog 30 registriert worden sind. Als nächstes weist der Katalog eine Feldanordnung 32 auf, die Klasseninformationsdatensätze speichert, und zwar einen pro exportierte Klasse. Der Klasseninformationsdatensatz in der Feldanordnung 32 besteht aus einer Struktur 33, die eine Anzahl von Parametern aufweist. Die Struktur weist ein erstes Feld 34 auf, das als Bibliothek bezeichnet wird und das auf die Bibliothek zeigt, die für den Code der bestimmten Klasse oder des bestimmten Funktionssatzes zuständig ist. Ein zweites Feld 35 speichert eine laufende Klassennummer, die für jede Instanz der Klasse einmalig ist; d. h. sie wird bei Registrierung der Klasse inkrementiert.
- Das nächste Feld 36 speichert einen VTable- Datensatzzeiger, der der Zeiger auf den VTable-Datensatz für diese Klasse ist. Ein nächstes Feld 37 speichert einen Klassen-ID, der ein Klassenbezeichner für die Klasse ist. Ein nächster Datensatz 38 speichert den Vaterklassen-ID. Dies ist der Klassen-ID für einen Vater dieser Klasse. Als nächstes werden mehrere Flags im Feld 39 gespeichert, die nachstehend ausführlicher definiert werden. Ein nächstes Feld 40 ist ein Klassenverknüpfungszeiger. Dieser zeigt auf eine Verknüpfungsstruktur zur Herstellung einer Verknüpfung mit dem Client-VTable-Datensatz. Feld 41 speichert einen Versionsparameter, der eine Version der Klassenimplementation anzeigt.
- Der Klasseninformationsdatensatz wird aus einem Bibliotheksbetriebsmittel mit einer Struktur geladen, die nachstehend mit Bezug auf Fig. 8 beschrieben wird.
- Fig. 3 stellt die Datensätze schematisch dar, die zur dynamischen Verknüpfung eines Funktionsaufrufs in einem Client mit einer Klasse oder einem Funktionssatz verwendet werden. Die Figur ist insgesamt entlang der Linie 50 geteilt, wobei Elemente über der Linie 50 während der Kompilierzeit mit dem Client verknüpft werden und Elemente unter der Linie 50 mit dem Gemeinschaftsbibliotheksmanager verknüpft werden. Der Client weist also einen Fragmentdatensatz 51 auf, der einen Funktionsverknüpfungscachespeicher für einen Zeiger auf die Implementation der aufgerufenen Funktion und einen Zeiger 52 auf den Client-VTable-Datensatz 53 bereitstellt. Der Client- VTable-Datensatz speichert den Klassenbezeichner für die Klasse oder den Funktionssatz und einen Klassenverknüpfungszeiger, der einen Satzverknüpfungscachespeicher bereitstellt. Der Klassenverknüpfungszeiger 54 zeigt auf eine Verknüpfungsstruktur 55, die einen Zeiger 56 auf einen Klasseninformationsdatensatz 57 im Klassenkatalog speichert. Der Klasseninformationsdatensatz weist einen Zeiger 58 auf den Klassen-VTable- Datensatz 59 auf. Der Klassen-VTable-Datensatz weist einen Zeiger 60 auf die tatsächliche VTable der Klasse und einen Zeiger 61 auf eine Exporttabelle für nichtvirtuelle Funktionen auf.
- Wenn der Klassenverknüpfungszeiger 54 null ist, wird eine Suchfunktion aufgerufen, die den Klassenkatalog 62 anspricht, um den Klasseninformationsdatensatz 57 für die entsprechende Funktion zu suchen. Wenn diese Funktion registriert ist, dann wird der Klasseninformationssatz 57 geliefert, und der Klassen-VTable-Datensatz 59 kann gelesen werden.
- Die Figur weist auch eine schematische Darstellung einer Lademaschine 64 auf. Die Lademaschine ist mit dem Klasseninformationsdatensatz 57 gekoppelt. Wenn die Klasse, die dem Klasseninformationsdatensatz entspricht, zu der Zeit, wo sie aufgerufen wird, nicht geladen ist, wird die Lademaschine 64 aufgerufen. Wenn die Information aus einem Langzeitspeicher in den internen Hochgeschwindigkeitsspeicher verschoben wird, werden der Klasseninformationsdatensatz 57 und der Klassen- VTable-Datensatz 59 mit den richtigen Zeigern und Werten aktualisiert.
- Fig. 4A, 4B bzw. 4C zeigen die tatsächlichen "C"- Definitionen für den Fragmentdatensatz, den Client-VTable- Datensatz und den Klassen-VTable-Datensatz gemäß der bevorzugten erfindungsgemäßen Implementation. Einzelheiten zu diesen Strukturen werden nachstehend in der Beschreibung einer bevorzugten Ausführungsform beschrieben. Sie sind in diesen Figuren aufgeführt, zur besseren Verständlichkeit und um bestimmte Merkmale darzustellen. Man kann sehen, daß der Client-VTable- Datensatz (Fig. 4B) Versionsinformation (fVersion, fMinVersion), die eine aktuelle Version für den Funktionssatz oder die Klasse anzeigt, mit der der Klassenverknüpfungszeiger verknüpft ist, und die laufende Nummer (fClass Serial. Number) für dieselbe aufweist. Der Klasseninformationsdatensatz 57 in Fig. 3 weist auch Versionsinformation für gegenwärtig geladene Klassen für einen Funktionssatz und die laufende Nummer für die gegenwärtig geladene Klasse oder den gegenwärtig geladenen Funktionssatz auf. Diese Felder werden verwendet, um Versionskompatibilität zwischen dem Client und der gegenwärtig geladenen Bibliothek sowie Gültigkeit der Verknüpfungsinformation sicherzustellen.
- Der Klassen-VTable-Datensatz 59 (Fig. 4C) weist auch einen Verwendungszählungsparameter (fUseCount) auf. Der Verwendungszählungsparameter wird immer dann inkrementiert, wenn eine Klasse aufgebaut wird, und dekrementiert, wenn eine Klasse abgebaut wird. Wenn die Verwendungszählung auf null zurückgeht, wird die Klasse oder der Funktionssatz aus dem internen Speicher entlassen.
- Fig. 5A und 5B stellen Flußdiagramme für die grundlegende Implementation der Laufzeitarchitektur dar. Der Algorithmus beginnt, indem eine Client-Anwendung einen Klassenkonstruktor oder eine Funktion mit dem Namen aufruft (Block 100). Der insgesamt durch eine gestrichelte Linie 90 umrissene Fragmentcode im Client mit einem passenden Namen verweist auf den verknüpften Fragmentdatensatz (Block 101). Der Fragmentcode prüft dann, ob der Fragmentdatensatz die Adresse für den Konstruktor oder die Funktion in seinem Funktionsverknüpfungscachespeicher aufweist (Block 102). Wenn ja, dann springt der Fragmentcode zur Adresse (Block 103). Dies ist die schnellste Art und Weise, wie eine Funktion ausgeführt werden kann.
- Wenn der Fragmentdatensatz keine gültige cachegespeicherte Adresse für die Funktion aufweist, dann ruft der Fragmentcode eine Zuteilroutine der ersten Ebene auf (Block 104).
- Die Zuteilroutine der ersten Ebene ist insgesamt durch eine gestrichelte Linie 91 umrissen. Der erste Schritt in dieser Routine ist es, einen Zeiger auf die Bibliotheksmanagerschnittstelle im Client in ein Hostregister zu laden (Block 105). Als nächstes wird die Distanz zur Zuteilroutine der zweiten Ebene aus den SLM-Globalvariablen im internen Speicher gelesen (Block 106). Als nächstes erfolgt anhand der im Block 106 gelesenen Distanz ein Sprung zur Zuteilroutine der zweiten Ebene (Block 107).
- Die Zuteilroutine der zweiten Ebene ist insgesamt durch eine gestrichelte Linie 92 umrissen. Die Zuteilroutine der zweiten Ebene beginnt, indem Zeiger für die Client- Bibliotheksmanagerschnittstelle und den Fragmentdatensatz in den Stapelspeicher geschoben werden (Block 108). Als nächstes wird die Suchfunktion für den Klassenkatalog aufgerufen (109).
- Die Suchfunktion ist insgesamt durch eine gestrichelte Linie 93 umrissen. Der erste Schritt in der Suchfunktion ist es, den Fragmentdatensatz und die Bibliotheksmanagerschnittstelle für den Client aufzunehmen (110). Mit dieser Information liest die Suchfunktion den Klassenbezeichner für die benannte Klasse oder den benannten Funktionssatz aus dem Client- VTable-Datensatz (Block 111). Als nächstes wird der Klassen- VTable-Datensatz (ein Satzdatensatz) anhand des Klassen-IDs gelesen (Block 112). Dieser Schritt kann mit dem Klassenverknüpfungszeiger für cachegespeicherte Klassen oder Funktionssätze erfolgen oder erfordert ein Suchen im Klassenkatalog. Wenn der Klassen-VTable-Datensatz gefunden ist, führt ihn eine Verknüpfungsmaschine aus, die insgesamt durch eine gestrichelte Linie 94 umrissen ist. Der erste Schritt in der Verknüpfungsmaschine ist es, den Funktionsfeldanordnungszeiger aus dem Klassen-VTable-Datensatz zu holen (Block 113). Als nächstes wird eine Feldanordnung nach der bestimmten aufgerufenen Funktion durchsucht (114). Als nächstes wird ein Zeiger auf die Funktion im Fragmentdatensatz für den Client gespeichert, der einen Funktionsverknüpfungscachespeicherwert darstellt (Block 115). Schließlich wird der Funktionszeiger an die Zuteilroutine der zweiten Ebene zurückgegeben (Block 116). Die Zuteilroutine der zweiten Ebene bereinigt dann den Ablauf und springt zur Funktion (Block 117).
- Fig. 6A, 6B und 6C stellt ein Flußdiagramm für den Schritt im Block 112 in Fig. 5B dar, der den Klassen-VTable- Datensatz als Antwort auf den Klassen-ID zurückgibt. Der Algorithmus beginnt also damit, daß der Klassen-ID als Eingangswert angenommen wird (Block 150).
- Mit dem Klassen-ID wird das Klassenkatalogobjekt aufgerufen, das zuerst die laufende Klassennummer im Client-VTable- Datensatz mit einer laufenden Globalstartnummer vergleicht, die vom Gemeinschaftsbibliotheksmanager aktualisiert wird. Der Gemeinschaftsbibliotheksmanager stellt sicher, daß alle laufenden Nummern gültiger Clients mindestens größer als die laufende Globalstartnummer sind.
- Wenn diese Prüfung erfolgreich ist, springt der Algorithmus zum Block 152, wo bestimmt wird, ob der Klassenverknüpfungszeiger in der Client-VTable null ist. Wenn er null ist, verzweigt sich der Algorithmus zum Block 161 in Fig. 6B. Wenn der Zeiger jedoch nicht null ist, dann wird der Klassendatensatz anhand der Information im Verknüpfungszeiger gelesen.
- Nach dem Lesen des TClass-Datensatzes wird die laufende Klassennummer in der Client-VTable mit derselben im TClass- Datensatz verglichen. Wenn sie nicht übereinstimmen, verzweigt sich der Algorithmus zum Block 161. Wenn sie übereinstimmen, wird die Bibliotheksdatensatz TLibrary für die Klasse aus der Information in TClass gelesen (Block 155). Der Bibliothekssatz zeigt an, ob die VTables für die Klasse initialisiert sind (Block 156). Wenn nicht, verzweigt sich der Algorithmus zum Block 162. Wenn sie initialisiert sind, wird die laufende "Code"-Nummer in der Client-VTable mit derselben im Bibliotheksdatensatz verglichen (Block 157). Wenn sie nicht übereinstimmen, verzweigt sich der Algorithmus zum Block 162.
- Wenn die laufenden Codenummern übereinstimmen, wird der Klassen-VTable-Datensatz als Antwort auf die Information des TClass-Datensatzes zurückgegeben (Block 158).
- Nach dem Lesen des Klassen-VTable-Datensatzes wird die Klassen-VTable-Datensatz-Verwendungszählung sowie die Bibliotheksverwendungszählung inkrementiert (Block 159). Nach Block 159 ist der Algorithmus beendet, wie im Block 160 angezeigt.
- Fig. 6B zeigt die Routine zur Verarbeitung der Zweige von den Blöcken 152, 154, 156 und 157. Für die Zweige von den Blöcken 152 und 154 beginnt diese Routine mit dem Block 161, der eine Klassensuchfunktion aufruft, um den TClass-Datensatz aus dem Klassenkatalog zu holen (Block 161). Nach dem Lesen des TClass-Datensatzes wird der Klassen-VTable-Datensatz als Antwort auf die Information in TClass gelesen (Block 162). Als nächstes werden die Klassen-VTable-Datensatz-Verwendungszählung und die Bibliotheksverwendungszählung inkrementiert (Block 163). Der Klassen-VTable-Datensatz wird durchgesehen, um zu bestimmen, ob er Zeiger auf die VTable und die Exporttabelle für die Klasse aufweist (Block 164). Wenn Zeiger vorhanden sind, wird der Algorithmus beendet (Block 165). Wenn nicht, wird eine Einrichtfunktion aufgerufen, um den Klassen- VTable-Datensatz zu initialisieren (Block 166). Die Einrichtfunktion wird in Fig. 6C beschrieben. Der Algorithmus beginnt mit einem Zugriff auf den Bibliotheksdatensatz, um zu bestimmen, ob der Code geladen ist (Block 167). Wenn der Code geladen ist, wird die Bibliotheksverwendungszählung inkrementiert (Block 168). Wenn der Code nicht geladen ist, wird die Bibliothek geladen und ihre Verwendungszählung inkrementiert (Block 169).
- Nach Block 168 oder 169 wird der Client-VTable- Datensatz aus der Bibliothek gelesen, und der Zeiger auf den Klassen-VTable-Datensatz wird gelesen (Block 170). Der aus dem Client-VTable-Datensatz in der Bibliothek geholte Zeiger wird verwendet, um den Klassen-VTable-Datensatz zu holen (Block 171). Als nächstes werden die Cachespeicherverknüpfungen im Client-VTable-Datensatz im Client und dieselben in der geladenen Bibliothek und die Cachespeicherverknüpfungen im TClass- Datensatz mit Information über den Klassen-VTable-Datensatz aktualisiert (Block 172). Schließlich wird der Algorithmus beendet (Block 173).
- Fig. 7 ist eine schematische Darstellung der Struktur von Bibliotheksdateien, die im Klassenkatalog dynamisch regitriert werden können. Die Bibliotheksdateien sind normalerweise auf einer Platte 200 gespeichert. Diese Bibliotheksdateien sind in einem Erweiterungsordner 201 registriert, der an der Anwenderschnittstelle der Vorrichtung, z. B. MacintoshTM- Computer, grafisch dargestellt ist. Der Erweiterungsordner weist eine Anzahl von Verwaltungsdateien 202 und mehrere Bibliotheksdateien 203, 204, 205 auf. Die Bibliotheksdateien sind alle im Klassenkatalog registriert. Die Bibliotheksdateien mit einem Dateityp "libr" 206 weisen eine Anzahl von Segmenten auf, einschließlich Codebetriebsmittel 207, ein Dateiverzeichnisbetriebsmittel "libr" 208 und ein Dateiverzeichnisbetriebsmittel "libi" 209. Die Codebetriebsmittel 207 weisen die Bibliothekscodesegmente, z. B. Klassen und generische Funktionssätze, auf. Das Dateiverzeichnisbetriebsmittel "libr" beschreibt die Bibliothek. Das Dateiverzeichnisbetriebsmittel "libi" führt Bibliotheken auf, von der diese Bibliothek abhängig ist. Das Dateiverzeichnisbetriebsmittel "libr" 208 ist in Block 210 ausführlicher dargestellt. Dieses Betriebsmittel weist ein Bibliotheks-ID-Feld 211 auf, das die Zeichenkette ist, die die Bibliothek identifiziert. Ein zweites Feld 212 in der Struktur 210 identifiziert den Codebetriebsmitteltyp. Ein drittes Feld 213 identifiziert die Schablonenversionsnummer für die Bibliotheksdatei. Ein viertes Feld 214 identifiziert die Versionsnummer der Bibliothek, die nach einem Standardprotokoll von den Entwicklern der Bibliotheken gepflegt wird. Das nächste Feld 215 speichert mehrere Bibliotheksflags. Das nächste Feld 216 identifiziert die Zahl der Elemente in einer exportierten Klasseninformationsfeldanordnung 217. Diese Informationsfeldanordnung 217 weist einen Datensatz pro exportierte Klasse in der Bibliothek auf. Jeder Datensatz weist einen Klassenbezeichner 218, Klassenflags 219, eine Versionsnummer der aktuellen Version der Klasse 220, eine niedrigste Versionsnummer für die abwärtskompatible Versionsnummer für die Klasse 221, eine Nummer 222, die die Nummer der Elemente in der folgenden Feldanordnung 223 der Vaterklassen-IDs anzeigt. Die Feldanordnung 223 der Vaterklassen-IDs weist den Kennzeichner jeder Vaterklasse auf. Die Information in diesem Betriebsmittel 210 wird verwendet, um bei Registrierung der Bibliothek die Klasseninformationsdatensätze für den Klassenkatalog zu erzeugen.
- Fig. 8 zeigt den Grundalgorithmus zum dynamischen Registrieren von Bibliotheken unter Verwendung der Struktur in Fig. 7.
- Wie in Block 300 dargestellt, bestimmt das Betriebssystem ein spezielles Verzeichnis, z. B. den Erweiterungsordner 201 in Fig. 7, und Anwendungen können zusätzliche Verzeichnisse für registrierte Bibliotheken bestimmen.
- Der Bibliotheksmanager bzw. Library Manager nimmt Betriebssystemaufrufe wahr, die anzeigen, daß eine Datei kopiert oder verschoben worden ist. Dann wird bestimmt, ob das Dateisubjekt des Aufrufs in den speziellen Ordnern oder in einem der zusätzlichen Ordner ist (Block 301).
- Wenn eine neue Datei gefunden wird, wird bestimmt, ob die neue Datei ein Gemeinschaftsbibliotheksbetriebsmittel ist. Wenn ja, wird die Bibliothek im Klassenkatalog registriert, indem Information bereitgestellt wird, um die TClass- Datensätze für die Klassen im Klassenkatalog zu füllen (Block 302). Wenn eine Bibliothek aus dem Ordner verschoben worden ist, läßt der Bibliotheksmanager diese registriert, bis sie nicht mehr verwendet wird. Nachdem sie nicht mehr verwendet wird, wird sie aus dem Klassenkatalog entfernt (Block 303).
- Der Gemeinschaftsbibliotheksmanager stellt auch Funktionen bereit, die mit den Clients verknüpft sind, und ermöglicht es ihnen, den Klassenkatalog für verschiedene Funktionen zu nutzen. Bestimmte Routinen weisen auf: eine neue Objektroutine, die mit Bezug auf Fig. 9A und 9B beschrieben wird, eine Variante einer neuen Objektroutine, die in Fig. 10 dargestellt ist, eine Objektüberprüfungsroutine, die in Fig. 11 dargestellt ist, eine Objektkonvertierungsroutine, die in Fig. 12 dargestellt ist, und eine GetClassInfo-Routine, die in Fig. 13 dargestellt ist.
- Wie in Fig. 9A bis 9B gezeigt, nimmt die neue Objektroutine als Eingabe den Klassenbezeichner für das neue Objekt und eine Anzeige eines Speicherpools zur Zuweisung des Objekts auf (Block 320). Mit dieser Information wird bestimmt, ob der Speicherpool tatsächlich für das Objekt zugewiesen ist. Wenn nicht, wird der Pool zugewiesen (Block 321). Als nächstes wird die Klassensuchfunktion im Klassenkatalog aufgerufen, um das TClass-Objekt für die identifizierte Klasse zu holen (Block 322). Als nächstes zeigen Flags, die im TClass-Objekt aktualisiert werden, an, ob die neue Objektroutine für die bestimmte Klasse unterstützt wird (Block 323). Wenn sie unterstützt wird, wird bestimmt, ob der TClass-Datensatz für die Klasse einer anderen Bibliothek als der Hauptverzeichnisbibliothek zugeordnet ist. Wenn es eine Hauptverzeichnisbibliotheksklasse ist, wird garantiert, daß sie immer geladen ist, und die Verwendungszählung wird inkrementiert (Block 324).
- Wenn die Klasse einer anderen Bibliothek als der Hauptverzeichnisbibliothek zugeordnet ist, wird eine Ladefunktion aufgerufen, um entweder die Bibliothek zu laden und dann die Verwendungszählung zu inkrementieren oder, wenn die Bibliothek bereits geladen ist, dann nur die Anwendungszählung zu inkrementieren (Block 325).
- Als nächstes wird das TClass-Objekt verwendet, um den Klassen-VTable-Datensatz zu lesen (Block 326). Mit den Flags im Klassen-VTable-Datensatz wird bestimmt, ob die neue Objektroutine für die Klasse (wieder) unterstützt wird (Block 327).
- Als nächstes wird die Größe des Objekts aus dem Klassen-VTable-Datensatz bestimmt, und ein Speicher dieser Größe wird dem Pool zugewiesen (Block 328).
- Als nächstes wird ein Zeiger auf den zugewiesenen Speicher gelesen (Block 329). Der Bibliotheksmanager fordert, daß die zweite freie Stelle in der Exporttabelle für Klassen in der Bibliothek einen Zeiger auf einen Konstruktor für die Klasse enthält. Der Zeiger für den Konstruktor wird somit aus der Exporttabellenspeicherstelle gelesen, die im Klassen- VTable-Datensatz angezeigt ist (Block 330). Mit dem Konstruktorzeiger wird der Konstruktor aufgerufen, der ein Objekt im zugewiesenen Speicher ablegt (Block 331).
- Als nächstes wird die Verwendungszählung um eins dekrementiert, um die Verwendungszählung zu aktualisieren (Block 332). Dies ist erforderlich, da der Ladefunktionsschritt im Block 325 die Verwendungszählung ebenso inkrementiert wie das Aufrufen eines Konstruktors im Block 330. Das Dekrementieren der Verwendungszählung ist also zum Aktualisieren der Verwendungszählung erforderlich. Nach der Dekrementierung der Verwendungszählung im Block 332 wird der Algorithmus beendet (Block 333). Der Client kann also einen Konstruktor für eine Klasse, die er zur Kompilierzeit nicht kannte, erreichen und aufrufen.
- Fig. 10 zeigt eine Variante der neuen Objektroutine, die eine bessere Typsicherheit hat. Insbesondere wenn der Client den Vater des zu erzeugenden neuen Objekts kennt, kann die Variante gemäß Fig. 10 aufgerufen werden. Die Variante in Fig. 10 nimmt als Eingabe den Vaterbezeichner für den Vater der Klasse, den Klassen-ID des zu erzeugenden neuen Objekts und die Speicherpoolzuweisungsparameter (Block 340). Als nächstes wird eine Klassenüberprüfungsfunktion, die mit Bezug auf Fig. 11 beschrieben wird, aufgerufen, um sicherzustellen, daß die identifizierte Klasse vom identifizierten Vater abgeleitet ist (Block 341). Wenn die Überprüfung erfolgreich ist, wird die neue Objektroutine in Fig. 9A und 9B für die identifizierte Klasse aufgerufen (Block 342).
- Fig. II zeigt die Klassenüberprüfungsroutine, die im Block 341 in Fig. 10 aufgerufen worden ist. Außerdem ist diese Routine für die Clients direkt verfügbar. Die Klassenüberprüfungsroutine beginnt damit, daß der Klassen-ID der Basisklasse und einer abgeleiteten Klasse geholt wird (Block 350). Als nächstes wird die Klassensuchfunktion des Klassenkatalogs aufgerufen, um den TClass-Datensatz für die abgeleitete Klasse zu holen (Block 351). Der TClass-Datensatz für die abgeleitete Klasse weist eine Liste von Vaterklassen auf. Die Liste wird durchgesehen, um zu bestimmen, ob die identifizierte Vaterklasse vorhanden ist (Block 352). Wenn die Vaterklasse gefunden ist, wird der Algorithmus beendet (Block 353). Wenn die Vaterklasse nicht gefunden wird, geht es der Reihe nach zum TClass-Datensatz jedes Vaters der abgeleiteten Klasse. Die Li ste der Väter für jeden Vater wird durchgesehen, um die identifizierte Vaterklasse zu finden, wobei dieser Rekursion bis zur Hauptverzeichnisklasse gefolgt wird. Der Algorithmus endet, wenn der Vater gefunden oder die Hauptverzeichnisklasse erreicht ist (siehe Anhang TLibraryManager::VerifyClass and:: internal VerifyClass).
- Wenn mehr als ein unmittelbarer Vater in der Liste der Väter für den TClass-Datensatz vorhanden ist, liegt ein Fall von Mehrfachvererbung vor. In diesem Fall muß die Vaterklassenhierarchie durchgesehen werden, um sicherzustellen, daß mindestens ein Vater als virtuelle Basisklasse erscheint (Block 355). Wenn der identifizierte Vater beim Klassenüberprüfungsaufruf als virtuelle Basisklasse nicht gefunden wird, dann wird bestimmt, daß er sich zum Zwecke dieser Funktion nicht auf die abgeleitete Klasse bezieht.
- Fig. 12 ist ein Flußdiagramm für eine Objektkonvertierungsroutine, die vom Gemeinschaftsbibliotheksmanager ausgeführt und durch die erforderliche Struktur der Objekte der Gemeinschaftsbibliotheksmanagerumgebung mit den Clients verknüpft wird. Mit dieser Funktion kann ein Client ein Objekt einer abgeleiteten Klasse als Vaterklassenobjekt konvertieren, auch wenn er möglicherweise die Struktur des Vaters zu der Zeit, wo er kompiliert wurde, nicht gekannt hat. Dieser Algorithmus nimmt als Eingabe einen Zeiger auf das Objekt und einen Bezeichner der Vaterklasse auf (Block 400). Als nächstes wird die Klasse des Objekts anhand der erforderlichen Struktur des Objekts bestimmt (Block 401). Diese Struktur ermöglicht ein Setzen des Zeigers auf die VTable als das erste Datenelement im Objekt. Außerdem ist die erste freie Stelle in der VTable ein Zeiger auf den VTable-Datensatz des Gemeinschaftsbibliotheksmanagers.
- Mit dem Klassen-ID des Objekts, der aus dem Klassen- VTable-Datensatz bestimmt wird, und dem Vater-ID, der bereitgestellt wurde, als das konvertierte Objekt berechnet wurde, wird dann die Klassenüberprüfungsroutine aufgerufen (Block 402). Wenn die Klassenüberprüfung erfolgreich ist, wird aus dem Klassen-VTable-Datensatz des Objekts bestimmt, ob eine Einfach- oder Mehrfachvererbung vorliegt (Block 403).
- Wenn eine Einfachvererbung vorliegt, dann wird der Algorithmus beendet, da in diesem Fall die Distanzen bestimmt sind (404). Wenn Mehrfachvererbung vorliegt, werden die richtigen Distanzen innerhalb des Objekts zu den Daten der Vaterklasse festgestellt (Block 405). Dies kann anhand der Stelle der Vaterklasse in der Hierarchie von Vaterklassen in den TClass-Datensätzen festgestellt werden (siehe Anhang TLibraryManager::CastObject and ::interact Cast Object).
- GetClassInfo ist eine Elementfunktion des TLibraryManager, oder es wird eine Nichtelementfunktion bereitgestellt, die gLibraryManager-> GetClassInfo für den Anwender aufruft. Wenn ein Klassen-id, der eine gegebene Basisklasse festlegt, und ein Fehlercodezeiger gegeben sind, gibt er eine TClassInfo für die gegebene Klasse zurück, wenn die Klasse im Klassenkatalog registriert ist. Die TClassInfo kann dann verwendet werden, um über alle abgeleiteten Klassen der gegebenen Basisklasse wiederholt zu werden. Wenn die Klasse nicht registriert ist und ein Fehler auftritt, gibt GetClassInfo Null zurück (siehe Anhang TLibraryManager::The GetClassInfo).
- Der GetClassInfo-Algorithmus ist in Fig. 13 dargestellt. Er umfaßt die folgenden Schritte:
- 1. Die LookupClass-Funktion mit dem Klassen-id aufrufen. Wenn sie einen Zeiger zurückgibt, der nicht Null ist, dann wissen wir, daß die Klasse im Klassenkatalog registriert ist. Wenn sie Null zurückgibt, dann wird der Fehlercode auf kNotFound gesetzt, und Null wird als Funktionsrückgabewert zurückgegeben (Block 500).
- 2. Mit dem fClasses-Feld des fClassCatalog, bei dem es sich um eine TCollection-Klasseninstanz handelt, wird die CreateIterator-Funktion aufgerufen. Wenn der Iterator nicht erzeugt werden kann, dann wird Null als der Funktionsrückgabewert zurückgegeben und der Fehlercode auf kOutOfMemory gesetzt (Block 501).
- 3. Eine TClassInfo-Instanz erzeugen und das fIterator- Feld auf den im Schritt 2 zurückgegebenen Iterator setzen. Das fBaseClassID-Feld auf den gegebenen Klassen-id setzen. Wenn die TClassInfo nicht erzeugt werden kann, wird Null als der Funktionsrückgabewert zurückzugeben und der Fehlercode auf kOutOfMemory gesetzt (Block 502).
- 4. Die Reset-Funktion des Iterators aufrufen, um die Wiederholung neu zu starten. Die TClassInfo als der Funktionsrückgabewert zurückgeben und den Fehlercode auf kNoError setzen (Block 503).
- Die Funktionen der TClassInfo, die die Verwendung der TClassInfo-Instanz einschließen, der von GetClassInfo:: zurückgegeben wird.
- Datenelemente von TClassInfo sind:
- Reset - startet die Wiederholung von Anfang an.
- Next - holt die nächste abgeleitete Klasse in der Liste. IterationComplete - gibt 'richtig' zurück, wenn Next für alle abgeleiteten Klassen der gegebenen Basisklasse aufgerufen worden ist.
- GetClassID - gibt den Klassen-id der abgeleiteten Klasse (fClassID) zurück.
- GetClassNewObjectFlag - gibt 'richtig' zurück, wenn der von GetClassID zurückgegebene Klassen-id verwendet werden kann, um ein Objekt mit der NewObject-Funktion zu erzeugen.
- GetClassPreloadFlag - gibt 'richtig' zurück, wenn das Klassen- id-Vorabladeflag gesetzt ist, um die Klassenimplementation zur Urladezeit vorab zu laden.
- GetClassSize - gibt die Größe der Datenstruktur für eine Instanz der Klasse zurück.
- GetLibrary - gibt die TLibrary für die Klasse zurück.
- GetLibraryFile - gibt die TLibraryFile für die Klasse zurück.
- GetVersion - gibt die gegenwärtige Version der Klasse zurück.
- GetMinVersion - gibt die niedrigste kompatible Version der Klasse zurück.
- Der Algorithmus für TClassInfo weist die folgenden Schritte auf:
- 1. Wenn die TClassInfo erzeugt wird, wird das fBaseClassID-Feld auf den an GetClassInfo übergebenen Klassen- id gesetzt, das fIterator-Feld auf einen Klassenkatalogiterator gesetzt, der die TClass-Datensätze wiederholt, die im Klassenkatalog registriert sind, und fclass wird auf die TClass für die Klasse gesetzt, die fBaseClassID entspricht.
- 2. Die Funktion Next setzt die Datenelemente fClassID, fLibrary, fLibraryFile, fVersion, fMinVersion, fNewObjectFlag, fFunktionSetFlag und fSize. Sie bekommt diese Information durch den fIterator vom nächsten TClass-Datensatz, der die gewünschte "wird abgeleitet von"-Beziehung der Klasse hat, die durch fBaseClassID gegeben ist.
- 3. Die oben aufgeführten "Getter"-("Hole"-)Funktionen geben die Information im entsprechenden Datenelement des TIterators zurück.
- 4. Wenn die Getter-Funktionen zum ersten Mal aufgerufen werden oder nachdem Reset aufgerufen worden ist, ist die zurückgegebene Information für die fBaseClassID-Klasse selbst bestimmt.
- Eine ausführlichere Beschreibung einer bestimmten Implementation des Gemeinschaftsbibliotheksmanagers ist unten mit Bezug auf einen Code ausgeführt, der für den MacintoshTM- Computer geschrieben ist.
- Der hier beschriebene Gemeinschaftsbibliotheksmanager (SLM) stellt dynamische Verknüpfungs- und Lademöglichkeiten für den 68K Macintosh bereit. Das System kann an jede vom Anwender gewünschte Plattform angepaßt werden. Der SLM ermöglicht dynamisches Laden, auch als bedarfsweises Laden bezeichnet, sowohl für prozedurale Programme als auch für C++- Programme. Dieses unterscheidet sich von der traditionellen Methode des Anlaufzeitladens, das auch als "volles transitives Schließen" bezeichnet wird, was bedeutet, daß alle erforderlichen Bibliotheken geladen und auf einmal verschoben werden, wenn eine Anwendung anläuft.
- Der SLM leistet Prozeduralprogrammierunterstützung zum Exportieren und Importieren von Funktionen aus C, Pascal, Assembler oder jeder Sprache mit kompatiblen Aufrufkonventionen. Außerdem leistet der SLM extensive Unterstützung zum Exportieren und importieren von C++-Klassen, mit Schwerpunkt auf der Bereitstellung der dynamischen Merkmale, die für den Aufbau von erweiterbaren Anwendungen und Systemkomponenten für Macintosh grundlegend sind.
- Gemeinschaftsbibliotheken können zu jeder Zeit installiert und transparent aufgerufen werden. Dies ist nicht abhängig davon, wo ein Client aufgebaut wird oder wo die Bibliotheken sind, die er verwendet, wie der Dateiname bzw. die Dateinamen lauten oder wieviele von ihnen schließlich während einer Sitzung verwendet werden können. Die Bibliotheken werden anhand von Verwendungszählungen dynamisch geladen und entladen. Der SLM sorgt für alle Einzelheiten des Bindens und Ladens, und der Client muß nur die Schnittstellen zu den Klassen und Funktionen kennen, die er verwenden will.
- Der SLM bietet Möglichkeiten zur Instanzierung von Objekten nach dem Klassennamen, zum Spezifizieren einer Klassenhierarchie und zum Überprüfen der Klasse eines Objekts oder der Klasse einer Klasse.
- Die Architektur für den SLM beruht auf der 68K- Laufzeitarchitektur und der MPW-Werkzeugarchitektur. Ein Aufbauwerkzeug für den SLM nimmt eine Exportdatei (.exp) und eine MPW-Objektdatei (.o) als Eingabe an und erzeugt eine Bibliotheksdatei. Dies erfolgt, indem diese Dateien verarbeitet werden und dann der MPW-Verknüpfer aufgerufen wird, um den Auftrag zu beenden.
- Bei C++-Bibliotheken beruht der SLM auf dem MPW/AT&T 2.1 CFront v-table-Zuteilmodell. Entwicklungswerkzeuge müssen vtables erzeugen, die mit diesem Modell kompatibel sind. Insbesondere gehen wir davon aus, daß der erste Eintrag in der v- table nicht verwendet wird - der SLM verwendet ihn, um auf eine Klasse "meta-data" zu zeigen.
- Der SLM erfordert außerdem, daß der v-table-Zeiger das erste Datenelement in einem Objekt ist, damit bestimmte Funktionen arbeiten. Da diese Funktionen die Klasse des Objekts nicht kennen (ihre Aufgabe ist es, die Klasse herauszufinden), können sie die class meta-Daten über den v-table-Zeiger finden, wenn er an einer bekannten Stelle im Objekt steht.
- Es ist theoretisch möglich, daß der SLM mehr als ein Zuteilmodell unterstützt, allerdings wäre es für eine Kommunizierfähigkeit erwünscht, mehr als ein Modell zu haben. Ein Zuteiler könnte zwischen verschiedenen Zuteilmodellen oder sogar verschiedenen Aufrufkonventionen entscheiden, die beträchtliche Laufzeitaufwand mit sich bringen würden. Es wäre möglich, daß verschiedene Zuteilmodelle nebeneinander bestehen und doch nicht miteinander kommunizieren.
- Der SLM und 68K-Bibliotheken unterstützen sowohl Einfachvererbungsklassen (von SI, SingleObject abstammend) als auch Mehrfachvererbungsklassen (von non-SingleObject abstammend).
- Ein Entwicklungswerkzeug, das den SLM in einer Nicht- MPW-Umgebung unterstützen will, muß ein 'libr'-Betriebsmittel, einen Satz Codebetriebsmittel und optional ein 'libi'- Betriebsmittel erzeugen, wie in Fig. 7 gezeigt. Das Sprungtabellenbetriebsmittel wird zur Aufbauzeit nicht modifiziert - es ist eine normale modellnahe Sprungtabelle. Es wird zur La dezeit vom SLM modifiziert, aber die Aufbauwerkzeuge müssen es nicht kennen. Die Logik, die die 32-Bit-Verschiebung durchführt und die Dateninitialisierungslogik sind Codebibliotheken, die statistisch im Bibliotheksinitialisierungssegment verknüpft sind.
- Gemeinschaftsbibliotheken haben ein Sprungtabellenbetriebsmittel ('code' 0) plus ein Initialisierungscodesegment ('code' 1) plus mindestens ein Implementationssegment ('code' 2 und aufwärts). Wenn mehr als eine Bibliothek in einer Bibliotheksdatei ist, muß der Betriebsmitteltyp für jeden Satz der Codebetriebsmittel eindeutig sein (normalerweise 'cd01', 'cd02' usw.).
- Bibliotheksbetriebsmittel - legt den Typ der 'code'- Betriebsmittel und die von dieser Bibliothek exportierten Klassen und Funktionssätze fest. Natürlich muß der Betriebsmittel-ID für jedes 'libr'-Betriebsmittel in einer Datei eindeutig sein.
- Sprungtabellenbetriebsmittel - ist immer in der Datei vorhanden, im Speicher nur vorhanden, wenn die -SegUnload-Option beim SLMBuilder verwendet wird. Man beachte, daß NoSegUnload die Standardoption ist.
- Initialisierungscodesegmentbetriebsmittel - enthält nur Code, der mit einem %A5Init- oder A5Init-Segment verknüpft ist und zur Initialisierungszeit verwendet wird, muß nur dann einen anderen Code enthalten, wenn nicht die -SegUnload-Option beim SLMBuilder verwendet wird.
- Implementationscodesegment(e) - enthält irgendeinen Implementationscode für die Bibliothek, einschließlich CleanupProc, wenn überhaupt. Häufig haben Bibliotheken nur ein Implementationssegment, obwohl es nicht stört, wenn sie mehrere haben. Implementationssegmente werden mit 2 und aufsteigend numeriert.
- Wenn der SLM eine Bibliothek lädt, wird das Sprungtabellenbetriebsmittel geladen, plus dem Initialisierungssegment. Nach Initialisierung wird dieses Segment freigegeben - es wird nur dann noch gebraucht, wenn die Bibliothek entladen und dann neu geladen wird.
- Wenn die "NoSegUnload"-Option verwendet wird (die NoSegUnload-Option ist beim LibraryBuilder die Standardoption), dann werden alle Codesegmente geladen. Die Sprungtabelle plus die für jedes Segment erzeugte Verschiebungsinformation wird verwendet, um die auf der Sprungtabelle beruhenden Adressen im Code zu absoluten Adressen zu verschieben, die auf die Zielfunktion im Zielcodebetriebsmittel zeigen. Das Sprungtabellenbetriebsmittel wird dann freigegeben. Wenn diese Option verwendet wird, sollte die Bibliothek normalerweise nur ein Implementationssegment haben, aber dies ist kein Erfordernis.
- Wenn die "SegUnload"-Option verwendet wird (SegUnload- Option beim LibraryBuilder), dann wird das Implementationssegment geladen, plus irgendwelche Segmente, die mit preload (Vorabladen) bezeichnet sind (ein Vorablade-Betriebsmittelbit kann segmentweise von einer Anweisung in der .r-Datei gesetzt werden), oder alle Segmente werden geladen, wenn eine Bibliothek selbst mit preload bezeichnet ist (Vorlade-Flag im Bibliotheksdeskriptor). Jeder auf der Sprungtabelle beruhende Verweis im Code wird verschoben, um auf die absolute Adresse des Sprungtabelleneintrags zu zeigen. Die Sprungtabelle wird modifiziert, um pc-relative jsr-Befehle anstelle von Segmentlader-Unterbrechungen zu enthalten. Der jsr geht kurz vor der Sprungtabelle (in der 32-Byte-Lücke) zum SLM-Segmentlader- Eintrittspunkt. Dadurch wird die Größe der Sprungtabelle auf 32K begrenzt, was kein Problem sein sollte, da Bibliotheken keine riesigen Anhäufungen von Code sein sollten - Bibliotheksdateien können ohne weiteres mehrere Bibliotheken in sich aufnehmen, wenn Packung ein Thema ist. Es handelt sich um einen jsr und keinen jmp, da der Segmentlader die Rückkehradresse verwendet, die nun auf die letzten beiden Bytes des Sprungtabelleneintritts zeigt, um zu berechnen, welches Segment zu laden ist. Zur Ladezeit schiebt der SLM die Segmentnummerinformation aus dem Sprungtabelleneintrag in ein Feld, das auf die Sprungtabelle folgt. Dies ist zurückzuführen auf die Tatsache, daß der pc-relative jsr 2 Bytes mehr als die ursprüngliche Segmentlader-Unterbrechung einnimmt. Man beachte, daß alle Manipulationen an der Sprungtabelle für einen Werkzeugentwickler transparent sind.
- Ein Segment wird geladen, wenn ein Sprungtabellen- (jt-)Eintrag aufgerufen wird und die Sprungtabelle dann modifiziert wird, um einen absoluten Sprung für alle jt-Einträge für dieses Segment zu enthalten. Wenn Segmente entladen werden, wird der pc-relative jsr bei jedem Eintrag für dieses Segment in die Sprungtabelle zurückgesetzt.
- Die Datensegment-Adressen (die "globale Welt", d. h. was auf A5 beruhen würde) werden zu der absoluten Adresse der Daten verschoben.
- Jede Anwendung, jede Erweiterung, jeder Treiber oder jedes andere selbständige Codebetriebsmittel auf dem Macintosh kann gemeinsame bzw. Gemeinschaftsbibliotheken verwenden. Natürlich kann ein Client auch eine andere Gemeinschaftsbibliothek sein. Eine Gemeinschaftsbibliothek kann Funktionen oder Klassen importieren und exportieren. Ein Nichtbibliotheksclient (kurz eine "Anwendung") kann nur Funktionen oder Klassen importieren. Eine Anwendung kann eine importierte Klasse weiter klassifizieren, aber sie kann keine Klasse exportieren. Dies ist eine bedeutungslose Einschränkung, da eine Anwendung Gemeinschaftsbibliotheken als Betriebsmittel in der Anwendung selbst enthalten oder einen speziellen Ordner registrieren kann, der Gemeinschaftsbibliotheken enthält, die effektiv ein Teil der Anwendung sind.
- Der Shared Library Manager bzw. Gemeinschaftsbibliotheksmanager beteiligt sich, indem er die Objektdatei, die dafür bestimmt ist, eine Gemeinschaftsbibliothek zu werden, prüft und modifiziert. Er erzeugt mehrere Quell- und Betriebsmitteldateien, die dann verwendet werden, um die Gemeinschaftsbibliothek zu erzeugen und um Clients mit verknüpfungsfähigen "Fragmenten" zu versorgen, um Zugriff auf die Funktionen und Klassen in der Gemeinschaftsbibliothek zu bekommen. In den Abschnitten, die nun folgen, untersuchen wir jede dieser Dateien.
- Die allererste der Dateien, die von dem SLM Library- Builder-Werkzeug erzeugt wird, ist die Datei SharedLib- Temp.stubs.a. Dies ist eine Assemblersprachdatei, die die Fragmente für alle die Funktionen enthält, die exportiert werden. Exportierte Funktionen gliedern sich in fünf Kategorien. Diese sind: 1) Funktionssatzfunktion; 2) Klassenkonstruktor; 3) Klassendestruktor; 4) virtuelle Klassenfunktionen; und 5) nichtvirtuelle Klassenfunktionen. Es gibt eine getrennte Zuteilfunktion für jede dieser Klassifikationen, und die Fragmente werden für jede geringfügig anders erzeugt. Jede wird nachstehend ausführlich untersucht. Zum Zweck der Erläuterung der Architektur wird eine exportierte Funktion in einem Funktionssatz verwendet.
- Für jede Zuteilfunktion gibt es fünf Teile. Die ersten zwei Teile werden vom Aufbauwerkzeug geliefert und sind für jede Funktion eindeutig. Die anderen drei Teile werden vom SLM geliefert.
- Der erste Teil ist eine Struktur, die als Fragmentdatensatz bezeichnet wird (siehe Fig. 6).
- Der Fragmentdatensatz enthält zwei vom Gemeinschaftsbibliotheksmanager intern verwendete Felder (das erste und das dritte Feld im oben angeführten Beispiel). Das zweite Feld ist ein Zeiger auf den ClientVTableRec. Der ClientVTableRec ist eine Struktur (siehe Fig. 6), die mit der Anwendung verknüpft ist und die alle Information hat, die der SLM braucht, um den Funktionssatz oder die Klasse, auf die vom Fragment verwiesen wird, dynamisch zu finden und zu laden.
- Die "C"-Definition des ClientVTableRec lautet wie folgt:
- Das fClassLinkPtr-Feld enthält Information, die vom SLM verwendet wird, um den Verknüpfungszeiger auf das interne TClass-Objekt, das alle Information enthält, die über die Klasse oder den Funktionssatz bekannt ist, im Cachespeicher zu speichern. Die beiden Laufnummernfelder werden verwendet, um sicherzustellen, daß die cachegespeicherte Information noch gültig ist (wenn die Bibliothek entladen worden ist und eine neue Version einer Klasse oder eines Funktionssatzes in der Bibliothek in einen registrierten Ordner verschoben wurde, ist jede cachegespeicherte Information ungültig). Die Versionsnummernfelder enthalten Information über die Versionsnummer der Klasse oder des Funktionssatzes, mit der bzw. dem die Anwendung des Anwenders (Codebetriebsmittel, Dateikennung usw.) verknüpft ist, und das fClassIDStr-Feld enthält den tatsächlichen Class-ID der Klasse oder des Funktionssatzes, so daß sie bzw. er im SLM-Katalog gefunden werden kann.
- Das letzte Feld im Fragmentdatensatz ist ein Index. Er informiert den SLM, welcher Eintrag in der Funktionssatz- VTable einen Zeiger auf die gewünschte Funktion enthält.
- Die meisten Fragmentzuteilungen treten in drei Geschwindigkeiten auf - sehr schnell, schnell und langsam. Eine sehr schnelle Zuteilung tritt auf, wenn man die Funktion bereits vorher verwendet hat. In diesem Fall enthält das erste Feld des Fragmentsatzes die Adresse der tatsächlichen Funktion und kann unmittelbar aufgerufen werden. Wenn man diese Funktion niemals vorher aufgerufen hat, dann wird ein Zuteilfragment aufgerufen, das bewirkt, daß der SLM den ClientVTableRec prüft. Wenn man bereits eine andere Funktion in der gleichen Klasse oder dem gleichen Funktionssatz verwendet hat, dann enthält der ClientVTableRec bereits cachegespeicherte Information über die Speicherstelle der Tabellen, die die Funktionsadressen enthalten. In diesem Fall wird das Fragment des Anwenders so aktualisiert, daß die Adresse der Funktion für die nächste Zeit im Cachespeicher gespeichert wird, und die Funk tion wird dann aufgerufen. Wenn der ClientVTableRec keine cachegespeicherte Information enthält, muß der SLM die Klasse oder den Funktionssatz anhand des im ClientVTableRec gespeicherten Class-ID suchen, die Bibliothek, die die Klasse oder den Funktionssatz enthält, laden, wenn sie nicht schon geladen ist, die cachegespeicherte Information im ClientVTableRec aktualisieren, die cachegespeicherte Information im Fragment aktualisieren und dann schließlich die Funktion aufrufen.
- Der zweite Teil des Zuteilmechanismus ist ein tatsächlicher Fragmentcode, mit dem ein Client verknüpft wird:
- Normalerweise werden zwei (oder vielleicht vier) Versionen des Fragments assembliert - eine als modellnah (MODEL = 0) und eine als modellfern (MODEL = 1). Es können auch Fehlersuchversionen vorhanden sein, die für jede mit Macsbug- Symbolen (MACSBUG = 1) erzeugt werden.
- Man beachte, daß das Fragment zuerst prüft, ob das erste Feld des Fragmentsatzes nicht null ist. Wenn ja, springt er nur mit dem dort gespeicherten Zeiger. Ansonsten ruft er eine Zuteilfunktion der ersten Ebene, die auch als _SLM11FuncDispatch bezeichnet wird, (oder eine der anderen vier Variationen dieser Funktion) auf.
- Die folgende Funktion ist der dritte Teil des Zuteilcodes:
- Die ersten beiden Anweisungen holen die SLM- Globalinformationen. Der SLM speichert seine Globalinformation in einer unteren Speicherstruktur, die als ExpandMemrec bekannt ist (die Speicherstelle $2B6 im Macintosh enthält einen Zeiger auf diese Struktur). Die SLM-Globalinformation ist als Zeiger unter der Distanzadresse $10C in dieser Struktur gespeichert. Eines der Felder in dieser Struktur enthält einen Vektor der Zuteilfunktionen. Dieser Zuteiler verwendet das fünfte Element im Vektor zum Zuteilen (dies ist der Vektor zum Zuteilen von Funktionen in Funktionssätzen).
- Der Code für diese Zuteilfunktion (und die anderen vier Variationen) wird im LibraryManager.o und LibraryManager.n.o bereitgestellt, so daß Clients mit ihn verknüpft werden können.
- Der vierte Teil der Fragmentzuteilung ist die Zuteilungsfunktion der zweiten Ebene, die in diesem Vektor gespeichert ist:
- Dieser Zuteiler ruft eine Funktion im TClassCatalog- Objekt auf, das der fünfte und letzte Teil der Fragmentzuteilung ist. Es folgt eine Teilvereinbarung für TClassCatalog:
- Es gibt fünf Routinen im TClass-Catalog, die jedem der fünf Zuteilverfahren entsprechen. Diese sind: 1) LookupFunction; 2) GetConstructor; 3)GetDestructor; 4) GetVTableEntry; und 5) GetExportEntry.
- Es ist nicht notwendig, daß ein erzeugter Code vtable- Distanzen zum Klassenkatalog kennt. Diese Distanzen kennt der vektorisierte Zuteilcode. Tatsächlich wurde der Zuteilcode spezifisch so vektorisiert, daß sich Distanzen im TClass- Katalog verändern könnten, ohne eine neue Kompilierung von Clients zu bewirken.
- Die fünfte und letzte Zuteilroutine führt das eigentliche Auffinden der Klasse und Speichern aller cachegespeicherten Werte durch.
- In den folgenden Codebeispielen handelt es sich bei Code und Strukturen, die eine fettgedruckte Anfangs- und Endanweisung haben, um Code, der mit einem Aufbauwerkzeg erzeugt werden muß, um eine Gemeinschaftsbibliothek zu erzeugen. Code, der nicht fettgedruckt ist, ist nur zur Bezugnahme dargestellt.
- Um eine Funktion zu importieren, muß ein Client die Schnittstellendatei aufweisen, wenn er kompiliert, (in C die .h-Datei) und mit einer Client-Objektdatei (.cl.o oder .cl.n.o) verknüpft werden, die vom Bibliotheksentwickler bereitgestellt wird. Die Client-Objektdatei enthält Client- Fragmente für Funktionen, die der Client aufruft.
- Man beachte den folgenden Beispielsfunktionssatz, der von der ExampleLibrary exportiert wird.
- Die FunctionSet-Vereinbarung in der Exportdatei (ExampleLibrary.exp) lautet wie folgt:
- Die Prototypen aus der Schnittstellendatei (ExampleLibrary.h) sind folgende:
- Das Aufbauwerkzeug, LibraryBuilder, erzeugt Fragmente, die für jede von einer gegebenen Bibliothek exportierte FunctionSet-Funktion mit dem Client zu verknüpfen sind.
- o Ein Fragment wird für jede Funktion erzeugt. Das folgende ist der Fragmentdatensatz und das Fragment, das für die "HelloC"-Funktion erzeugt wird (in SharedLibTemp.stubs.a):
- Das folgende ist die Struktur des Fragmentdatensatzes in C:
- Wenn das Fragment aufgerufen wird, prüft er zuerst, ob die Adresse der Funktion bereits im Cachespeicher gespeichert ist. Wenn ja, springt er unmittelbar zu der Funktion. Andernfalls springt er mit dem Fragmentdatensatz als Parameter im Register A0 zum Funktionszuteiler (_SLM11FuncDispatch). Der Fragmentzuteiler ermittelt dann die Adresse des tatsächlichen Zuteilcodes aus einer globalen Einrichtung des unteren Speicherbereichs, als der SLM ursprünglich geladen wurde, und er springt zu diesem Code. Durch diesen Extra-Umweg hat der SLM die Flexibilität, den Funktionslade- und -zuteilmechanismus zu modifizieren, ohne den Client-Code zu berühren (da Clients mit dem _SLM11FuncDispatch-Code verknüpft sind).
- o Das folgende ist der Funktionszuteiler, der mit dem Client verknüpft ist.
- o Das folgende ist der tatsächliche Funktionszuteiler, der mit dem Gemeinschaftsbibliotheksmanager zwecks Verweisung verknüpft ist:
- Die CatVTable.LookupFunction ist ein Aufruf an das TClassCatalog::LookupFunction-Verfahren.
- o Ein ClientVTableRec wird pro Funktionssatz (der in SharedLibTemp.stubs.a mit dem Client zu verknüpfen ist) erzeugt:
- Der Initialisierungscode wird in zwei Dateien erzeugt: SharedLibTemp.init.a und SharedLibTemp.init.c. Der größte Teil der erzeugten Codes ist in "C", aber für jede Klasse oder jeden Funktionssatz wird ein ClientVTableRec erzeugt, der in die Assemblerdatei gebracht wird. Man kann die ClientVTableRec- Definition in "C" schreiben (die eingefügte "C"-Zeichenkette ist eine etwas größere Herausforderung, ist jedoch zu bewältigen), aber wir wollen sie in Assembler lassen. Wenn der In itialisierungscode des Anwenders mit seiner Fragmentbibliothek verknüpft wird, muß ein ClientVTableRec, genau genommen, nicht zur Initialisierung erzeugt werden, es ist natürlich einfacher, einen zu erzeugen.
- o Die Vektortabelle wird in der SharedLibTemp.init.c erzeugt (die mit der Bibliothek zu verknüpfen ist):
- Der SLM ermöglicht es auch, daß Funktionen nach dem Namen exportiert werden. Wenn eine Funktion nach dem Namen exportiert wird, wird eine weitere Struktur erzeugt. Wenn man annimmt, daß die HelloC-Routine und die GOODBYEPASCAL-Routine nach dem Namen exportiert würden, so würde der folgende Extracode erzeugt werden:
- Jede freie Stelle, die einer Funktion entspricht, die nicht nach dem Namen exportiert wird, wird mit einem (char*)- 1L gefühlt. Eine freie Stelle mit einem Null-(0-)Zeiger schließt die Liste der Namen ab. Ein Zeiger auf diese Liste von Namen ist im ersten Eintrag der Vektortabelle gespeichert:
- o Eine Initialisierungsfunktion wird für jeden Funktionssatz erzeugt.
- Zuerst soll die Anfangsanweisung gezeigt werden, die für die (in SharedLibTemp.init.c erzeugte) Initialisierungsdatei erzeugt worden ist:
- Es folgt die (in SharedLibTemp.init.c erzeugte) SVR- Funktion (SVR bedeutet Setup VTableRec):
- Der erste Parameter für die SVR-Funktion ist als VTableRec bekannt.
- Das folgende ist die Definition der VTableRec-Struktur. Diese Information ist lediglich zur Verweisung.
- Der VTableRec wird intern vom SLM verwendet, um mit der Information über jeden Funktionssatz oder jede Klasse auf dem laufenden zu bleiben. Ein Bibliotheksinitialisierungscode liefert alle Information, die der SLM benötigt, um die VTableRec zu füllen.
- o Eine Initialisierungsfunktion pro Bibliothek wird erzeugt, die den SLM aufruft, um alle ClientVTableRecs und SVR- Funktionen zu registrieren. Dieses Beispiel zeigt eine Initialisierung für die Beispielbibliothek, die den Funktionssatz ExampleFSet und die Klasse TExampleClass hat. Diejenigen Teile dieses Codes, den der Anwender ändern würde, je nachdem, was er initialisiert, sind unterstrichen.
- Dieser Abschnitt untersucht die Fragmenterzeugung für eine C++-Klasse, die durch Einfachvererbung entstanden ist. Dies schließt sowohl Formen von aus -SingleObject abgeleiteten vtablen als auch AT&Tv2.1-Standardklassen ein. Klassen, die durch Mehrfachvererbung entstehen (sich von mehr als einer Vaterklasse ableiten), werden in einem getrennten Abschnitt behandelt.
- Das folgende ist die Definition der TExampleClass (aus ExampleClass.h)
- Konstruktorfragmente werden für jeden Konstruktor einer Klasse erzeugt. Wenn die Exportdatei (mit einem noMethodStubs- oder nostubs-Flag) festlegt, daß keine Konstruktorfragmente zu exportieren sind, dann müssen die Konstruktorfragmente im Assemblersprachteil (SharedLibTemp.Init.a) der Initialisierungsdatei erzeugt werden. Dies ist so, damit Verwendungszählungen für jede Klasse richtig aktualisiert werden können.
- o Ein Fragmentdatensatz wird erzeugt, um sowohl mit dem Client als auch mit der Bibliothek (je nach Bedarf in Shared- LibTemp.stubs.a oder SharedLibTemp.init.a) verknüpft zu werden. Dieser Datensatz wird wie der Datensatz für einen Funktionssatz verwendet - er enthält cachegespeicherte Information, die verwendet wird, um die Zuteilung zu beschleunigen. Außerdem enthält er den Index in die "structor table" zur tatsächlichen Adresse des Konstruktors (siehe Abschnitt über Klasseninitialisierung, um Information über die Erzeugung dieser Tabelle zu finden).
- o Ein Konstruktorfragment wird erzeugt, um sowohl mit dem Client als auch mit der Bibliothek (je nach Bedarf in SharedLibTemp.stubs.a oder SharedLibTemp.init.a) verknüpft zu werden:
- Man beachte, daß der Konstruktor keine cachegespeicherte Information verwendet, um direkt zum Konstruktor zu springen. Dies ist so, damit Verwendungszählungen aktualisiert werden können (siehe nächsten Punkt).
- o Das folgende ist der Konstruktorfunktionszuteiler, der mit dem Client verknüpft ist. Dies dient nur zur Verweisung - der Client sollte mit der vom SLM gelieferten Version verknüpft werden.
- Unter normalen Umständen ist nur das Speichern des Verwendungszählers des VTableRec erforderlich, damit die Zuteilung angemessen schnell ist. Die einzige Zeit, die der allgemeinere Zuteilmechanismus benötigt, um aufgerufen zu werden, tritt auf, wenn der Konstruktor vom gegenwärtigen Client niemals vorher aufgerufen worden ist und es unter allen Clients des SLM keine ausstehenden Instanzen dieser Klasse gibt.
- Wenn natürlich der Compiler des Anwenders verschiedene Bezeichnungskonventionen für Konstruktoren hat, muß er Fragmente erzeugen, die den gleichen Namen haben wie die erzeugten (siehe Abschnitt über Initialisierung, um weitere Information dazu zu finden).
- o Das folgende ist der tatsächliche Konstruktorfunktionszuteiler, der mit dem Gemeinschaftsbibliotheksmanager verknüpft ist. Dies dient lediglich zur Verweisung:
- Der CatVTable.GetConstructor ist ein Aufruf an das TClassCatalog::GetConstructor-Verfahren.
- Destruktorfragmente werden erzeugt für den Destruktor einer exportierten Klasse. Wenn die Exportdatei (mit dem noMethodstubs- oder noStubs-Flag) festlegt, daß das Destruktorfragment nicht zu exportieren ist, dann muß das Destruktorfragment im Assemblersprachteil (SharedLibTemp.Init.a) der Initialisierungsdatei erzeugt werden. Dies ist so, damit die Anwendungszählungen für jede Klasse richtig aktualisiert werden können.
- o Das Destruktorfragment wird erzeugt, um sowohl mit dem Client als auch mit der Bibliothek (nach Bedarf in Shared- LibTemp.stubs.a oder SharedLibTemp.init.a) verknüpft zu werden. Man beachte, daß der Fragmentdatensatz für einen Destruktor geringfügig kleiner ist als einer für einen Konstruktor oder eine normale Funktion. Dies ist so, weil wir den Index zum Destruktor in dieser Tabelle nicht speichern müssen - es sind immer zwei (siehe Abschnitt über Klasseninitialisierung, um weitere Information zu finden).
- Man beachte, daß der Destruktor keine cachegespeicherte Information verwendet, um direkt zum Destruktor zu springen. Dies ist so, damit Verwendungszählungen aktualisiert werden können (siehe nächsten Punkt).
- Das folgende ist der Destruktorfunktionszuteiler, der mit dem Client verknüpft ist. Dies dient nur zur Verweisung - der Client sollte mit der vom SLM gelieferten Version verknüpft werden. Der DestStub-Datensatz sieht aus wie ein Funktionsfragmentdatensatz, außer daß er ein Feld kürzer ist (er benötigt das funcID-Feld nicht (dieses ist bekanntlich zwei (2)).
- Unter normalen Umständen ist lediglich die Dekrementierung der Verwendungszählung des VTableRec erforderlich, damit eine Zuteilung angemessen schnell ist. Die einzige Zeit, die der allgemeinere Zuteilmechanismus benötigt, um aufgerufen zu werden, tritt auf, wenn der Destruktor vom aktuellen Client vorher niemals aufgerufen worden ist und wir die letzte ausstehende Instanz dieser Klasse unter allen Clients des SLM zerstören.
- o Das folgende ist der gegenwärtige Destruktorfunktionszuteiler, der mit dem Gemeinschaftsbibliotheksmanager verknüpft ist. Diese Funktion ist die komplexeste der Zuteilfunktionen. Der Grund dafür ist, daß das Aufrufen des Destruktors eines Objekts bewirken kann, daß eine Bibliothek entladen wird. Das Entladen tritt nur auf, wenn SystemTask aufgerufen wird. Wenn jedoch der Destruktor SystemTask aufrufen müßte, dann könnte dies sehr störend sein, so daß wir einiges zu tun haben, sicherzustellen, daß die Bibliothek erst entladen werden kann, wenn wir vom Destruktor zurückkehren. Dies dient lediglich der Verweisung:
- Der CatVTable.GetDestructor ist ein Aufruf an das TClassCatalog::GetDestructor-Verfahren.
- Ein virtuelles Verfahrensfragment wird für jede virtuelle Funktion erzeugt, die mit dem Client (in SharedLib-Temp.stubs.a) verknüpft werden kann, wenn der Client nicht No-Stubs oder NoVirtualStubs in der Exportvereinbarung für die Klasse festgelegt hat. Diese Fragmente werden nur von einem Client verwendet, der Stapelobjekte erzeugt, da der Compiler einen direkten Aufruf erzeugt, wenn die Punktsyntax verwendet wird. Der Compiler ist "schlau" und "kennt" die Klasse des Objekts, so daß er keinen indirekten v-table-Aufruf erzeugt. Es wäre besser für SLM, wenn der Compiler eine Option hätte, um irgendwie v-table-Aufrufe zu erzeugen.
- Man beachte, daß wir bei den virtuellen Verfahrensfragmenten wiederum die tatsächliche Adresse der Funktion im Cachespeicher speichern und sie direkt aufrufen können.
- o Das folgende ist der virtuelle Funktionszuteiler, der mit dem Client verknüpft ist.
- o Das folgende ist der tatsächliche virtuelle Funktionszuteiler, der mit dem Gemeinschaftsbibliotheksmanager verknüpft ist.
- Viele Klassen verwenden sowohl virtuelle als auch nichtvirtuelle Funktionen. Durch virtuelle Funktionen können Unterklassen das Verhalten einer Klasse bestimmen, während dies durch nichtvirtuelle Funktionen nicht möglich ist. Der SLM unterstützt Fragmente, damit nichtvirtuelle Verfahren erzeugt werden (automatisch erzeugt werden, wenn in der Exportvereinbarung für die Klasse nicht noStubs oder noMethodStubs festgelegt ist). Man beachte, daß der SLM statistische Verfahren auf diese Weise nicht automatisch exportiert. Statische Verfahren sollten normalerweise in einem Funktionssatz exportiert werden, da keine Instanz der Klasse existieren muß, damit das Verfahren als gültig aufgerufen werden kann.
- o Ein nichtvirtuelles Elementfunktionsfragment wird für jede nichtvirtuelle Elementfunktion erzeugt (die mit dem Client in SharedLibTemp.stubs.a zu verknüpfen ist).
- o Das folgende ist ein nichtvirtueller Funktionszuteiler, der mit dem Client verknüpft ist.
- o Das folgende ist der tatsächliche nichtvirtuelle Funktionszuteiler, der mit dem Gemeinschaftsbibliotheksmanager verknüpft ist.
- Statische Verfahren sollten normalerweise nach Funktionssätzen exportiert werden, da sie keiner Instanz eines Objekts zugeordnet sind. Man kann ein spezifisches statisches Verfahren exportieren, indem man in seiner Funktionssatzvereinbarung "exports=< ClassName> ::< StaticMethod> " festlegt, oder man kann alle statischen Verfahren einer Klasse exportieren, indem man "exports = static < ClassName> " in der Vereinbarung festlegt.
- Dieser Abschnitt untersucht den Initialisierungscode für eine C++-Klasse, die durch Einfachvererbung entstanden ist. Dies schließt sowohl aus SingleObject abgeleitete Formen von vtables als auch AT&T v2.1-Standardklassen ein. Klassen, die durch Mehrfachvererbung entstehen (sich von mehr als einer Vaterklasse ableiten), werden in einem getrennten Abschnitt behandelt.
- o ClientVTableRecord für TExampleClass:
- Natürlich wird die vtable für TExampleClass vom Compiler erzeugt. Das Symbol dafür wird importiert (SharedLibTemp.init.c):
- Die Symbole für die nichtvirtuellen Elementfunktionen (in diesem Fall GetGlobalRef) und den Konstruktor und Destruktor werden importiert. Die Namen des Konstruktors und des Destruktors sind mit einem "q" verstümmelt, um sie von den Fragmenten zu unterscheiden.
- Der SLM modifiziert die Objektdatei, die den Konstruktor und den Destruktor enthält, so daß sich deren Namen unterscheiden. Dies erfordert, daß ein Verweis auf den Konstruktor oder Destruktor aus der Bibliothek auch über das Fragment verläuft. Dies ist so, damit Verwendungszählungen aktualisiert werden können. Wenn eine Bibliothek ein Objekt erzeugen, es an den Client übergeben und den Client veranlassen müßte, das Objekt zu zerstören, könnte die Bibliothek auch dann entladen werden, wenn ausstehende Verweise auf sie vorhanden wären, da kein Aufbau, sondern ein Abbau die Verwendungszählung inkrementierten würde.
- Das Fragment für den Konstruktor (der ohne das 'q') wird von NewObject aufgerufen. Die echten Konstruktoren und Destruktoren (die mit der q-Verstümmelung) sind Exporttabellen, so daß sie von den Fragmenten aufgerufen werden können. Die Originalsymbole für die Konstruktoren und Destruktoren in der Objektdatei (.o file) für die Bibliothek werden vom LibraryBuilder-Werkzeug "q-verstümmelt".
- Zwei Exporttabellen werden erzeugt. Eine für die Konstruktoren und Destruktoren (_extbl_< ClassName> ) und einer für die nichtvirtuellen Funktionen (_exptbl_< ClassName> ).
- Man beachte, daß der erste Eintrag in die "extbl" auf die "exptbl" zeigt. Dadurch kann eine spätere Version der Bibliothek neue nichtvirtuelle Verfahrensexporte und neue Konstruktoren haben. Die ersten vier Einträge der _extbl_ sind immer fest. Sie können null sein, wenn die entsprechende Tabelle oder Funktion nicht existiert. Der zweite Eintrag zeigt immer auf das Fragment für den Standardoptionskonstruktor (der Konstruktor ohne Argumente). Der dritte Eintrag zeigt immer auf den "echten" Destruktor, und der vierte Eintrag zeigt immer auf den "echten" Standardoptionskonstruktor. Alle Einträge nach dem vierten sind für andere Versionen der Konstruktoren bestimmt, und sie enthalten immer Zeiger auf die "echte" Version (_ctq_) dieser Konstruktoren.
- o Der tatsächliche Initialisierungscode muß dann erzeugt werden.
- Dieser Code führt verschiedene Dinge durch. Das erste ist die Initialisierung des VTableRec. Die Parameter für den InitVTableRec-Aufruf sind wie folgt:
- 1) ein Zeiger auf den Klassenkatalog, der aus den GetClass- Catalog-Makros geholt wird.
- 2) ein Zeiger auf VTableRec, der ursprünglich an die Initialisierungsfunktion des Anwenders übergeben worden ist.
- 3) ein Zeiger auf die vtable für die Klasse.
- 4) ein Zeiger auf die Exporttabelle für die Klasse.
- 5) ein Zeiger auf den ClientVTableRec der ersten "gemeinsamen" Vaterklasse, der rückwärts auf die Hierarchie schaut. Normalerweise ist es der ClientVTableRec der Vaterklasse des Anwenders. Wenn jedoch die Vaterklasse keine gemeinsame Klasse ist, dann schaut man auf dessen Vater usw., bis man eine gemeinsame Vaterklasse findet. Man läßt diesen Parameter Null (null), wenn keine gemeinsame Vaterklasse vorhanden ist.
- 6) Die Größe des Objekts in Bytes. Dieser Parameter ist optional und kann auf null gesetzt werden, wenn man will, daß die Klasse mit der NewObject-Funktion instanziert werden kann. Wenn dies der Fall ist, muß man die Größe als negative Zahl bereitstellen, deren absoluter Wert die Größe des Objekts in Byte ist.
- 7) Der letzte Parameter ist ein Flag, der den SLM über den VTableRec informiert. Für durch Einfachvererbung entstandene Klassen werden nur zwei Werte verwendet. Null (oder 0) zeigt an, daß die Klasse von SingleObject oder HandleObject erbt und ein vtable-Format hat, das nur ein Feld von Funktionszeigern ist. Ein Wert (char*)-1L zeigt an, daß die vtable das Format einer AT&T V2.1 vtable hat, das folgendermaßen aussieht:
- Dieser Abschnitt untersucht die Fragmenterzeugung für eine C++-Klasse, die durch Mehrfachvererbung entstanden sind. Es folgt ein Satz von Vereinbarungen für mehrere Klassen, die in der Definition der Klasse TMixedClass2 kulminiert. Dies sind die Klassen, die verwendet werden, um die Erzeugung von Code für durch Mehrfachvererbung entstandene Klassen zu demonstrieren.
- Alle Fragmente für durch Mehrfachvererbung entstandene Klassen werden auf genau die gleiche Weise wie die für durch Einfachvererbung entstandene Klassen erzeugt. Dies funktioniert, da alle geerbten virtuellen Funktionen in der primären vtable der Klasse vorhanden sind.
- Wenn ein Fall auftritt, wo dies nicht so ist, schafft der SLM eine Möglichkeit, sich damit zu befassen. Es wird ein hohes Bit (0x8000) des Indexwertes (ganz gleich für welche vtable die virtuelle Funktion vorhanden ist) gesetzt und ein zweites kurzes Feld (zwei Bytes) unmittelbar nach diesem in den Fragmentsatz hinzugefügt, was der Indexzahl des VTableRec entspricht (0 = primär, 1 = der nächste usw.).
- Dieser Abschnitt untersucht den Initialisierungscode für eine C++-Klasse, die durch Mehrfachvererbung entstanden ist. Die Situation ist hierbei sehr viel anders als bei durch Einfachvererbung entstandene Klassen. Man bedenke: Wenn man es bei der oben beschriebenen Hierarchie mit einem MMixin1-Objekt zu tun hat, muß die Information, ob es sich um ein wahres MMixin1-Objekt oder um ein in ein MMixin1-Objekt konvertiertes TMixedClass2-Objekt oder sogar um ein in ein MMixin1-Objekt konvertiertes TMixedClass-Objekt handelt, verfügbar gemacht werden, nämlich über die Distanz zurück zum "Haupt"-Objekt. Dadurch kann die SLM-Funktion CastObject richtig mit Objekten arbeiten, die Instanzen von durch Mehrfachvererbung entstandenen Klassen sind.
- Diese Information ist im MMixin1 VTableRec gespeichert, der in der MMixin1 vtable gespeichert ist. Für ein MMixin1- Objekt, das "selbständig" ist, ist jedoch ein anderer VTable- ReC erforderlich als für ein MMixin1-Objekt, das Teil eines TMixedClass2-Objekts ist. Der Grund dafür ist, daß die Distanz zum "Haupt"-Objekt bei einem "selbständigen" Objekt null und bei einem der vielen Väter eines "Haut"-Objekts wahrscheinlich nicht null ist.
- Dies bringt uns zu dem Schluß, daß, um eine durch Mehrfachvererbung entstandene Klasse zu initialisieren, VTableRecs initialisiert werden müssen, damit die Dinge glatt laufen.
- Die Initialisierung für die Klassen MMixin1, MMixin2 und MMixin3 sind genau das, was man für durch Einfachvererbung entstandene Klassen erwartet:
- Bei allen diesen Klassen ist der Zeiger auf den Vater- ClientVTableRec Null, die Größen sind acht Bytes lang und poaitiv (was bedeutet, daß sie mit NewObject instanziert werden können), und der letzte Parameter ist ein (char*)0x0001, was bedeutet, daß das vtable-Format das AT&T v2.1-Standardformat ist (Man beachte, daß eine 0 als dieser letzte Parameter anzeigte, daß das vtable-Format das einer Klasse war, die von Singleobject geerbt hat und daß dies eine primäre vtable ist. Grundsätzlich ist das erste Byte des Zeigers ein "Zuteilcode" - 0 bedeutet SingleObject-Zuteilung, 1 bedeutet AT&T v2.1- Zuteilung, und 2 bedeutet SingleObject-Typ-Zuteilung, aber nicht in einer SingleObject- oder HandleObject-Unterklasse.
- Das nächste Byte informiert darüber, um was für einen VTableRecord es sich handelt. Null (0) bedeutet die primäre vtable. Eins (1) bedeutet, daß er eine "Vater"-vtable ist. Eine "Vater"-vtable bewahrt den ClientVTableRec der Vaterklasse auf, von der die vtable erbt. Man beachte, daß dies nicht das gleiche ist wie die Klasse von Objekten, von denen wir ableiten. Zwei (2) bedeutet, daß es sich um eine "virtuelle Vater"- vtable handelt. Ein "virtueller" Vater erbt die vtable von einer "Vater"-Klasse genau wie eine "Vater"-vtable, aber die Klasse, von der wir ableiten, ist eine "virtuelle" Basisklasse.
- Der SLM nimmt an, daß bei den sekundären vtables, die erzeugt werden, die ersten acht Bytes der vtable nicht verwendet werden.
- TMainClass ist eine nichtgemeinsame Klasse, so daß keine Initialisierung (oder Fragmente) für sie erzeugt werden. Die nächste Klasse, für die Initialisierung erzeugt werden soll, ist TMixed Class. Wenn man den erzeugten Code anschaut, bemerkt man, daß man sich Namen für alle die Extra-vtables ausdenken können muß, die eine durch Mehrfachvererbung entstandene Klasse erzeugt, sowie welche Einträge in die vtable zu der Klasse selbst gehören und welche geerbt sind.
- Der SLM kopiert auch dynamisch Funktionszeiger von geerbten vtables, um zu vermeiden, mit Fragmenten verknüpft zu werden. Um zu verhindern, daß die Fragmente irgendwie verknüpft werden, wenn das LibraryBuilder-Werkzeug die vtables in der Objektdatei abfragt, ersetzt er Aufrufe an geerbte Funktionen mit einem Aufruf an_pure_virtual_called. Dadurch wird verhindert, daß der Verknüpfer alle Fragmente im Code verknüpft.
- Ein Paar Schlüsselpunkte, die man über den Code auf den vorherigen Seiten wissen muß. Der erste ist der, daß es nicht streng notwendig ist, Verfahren, die geerbt werden, dynamisch zu kopieren. Wenn man dies nicht tut, wird die vtable mit Fragmenten zu den geerbten Verfahren verknüpft, die zwar gut arbeiten, aber geringfügig langsamer sind.
- Es ist nicht unbedingt notwendig, die Objektdatei zu modifizieren, um einen geerbten Verweis in der vtable auf _pure_virtual_called zeigen zu lassen. Man könnte auch noch die Zeiger aus der Vater-vtable des Anwenders zur Laufzeit kopieren, und es würde nichts weiter geschehen, als daß die Fragmente unbenutzt bleiben, da sie keiner verwendet, so daß die Bibliothek des Anwenders geringfügig größer ist, als sie sein sollte.
- Es ist jedoch wichtig, daß man irgendwie die Distanz der Unterklasse aus der Hauptklasse bestimmt und diese im .func-Feld des ersten vtable-Eintrags für jeden VTableRec (d. h. vier Bytes beginnend mit Distanz 4 in der vtable) speichert. Der SLM hat dies zur Laufzeit entschieden, wobei die Kenntnis verwendet wird, daß das .o-Feld jedes vtable- Verfahrens, das durch die Hauptklasse bestimmt worden ist, diese Distanz bereits dort gespeichert hat. Dies war leichter, als zu versuchen, die Klassenvereinbarungen vollständig aufzugliedern (mit allem Begleitwissen der Auffüllregeln usw.), um sie zu bestimmen - es kann jedoch jedes Verfahren verwendet werden, das für eine gegebene Umgebung funktioniert. Die Distanz ist immer eine negative Zahl.
- Jetzt kommen wir zum Initialisierungscode für die Klasse TMixedClass2.
- Damit das optionale Kopieren von Verfahren funktioniert, ist es wichtig, daß die Reihenfolge der vtables die gleiche ist, ganz gleich, welcher C++-Compiler die vtables erzeugt hat. Aus dem obigen Beispiel wissen wir, daß wir aus den zweiten und dritten vtablen in der Liste der für TMixedClass erzeugten vtablen erben müssen (im übrigen ist zu beachten, daß man die Größe des VTableRec weitergegeben hat, so daß man die nötigen Berechnungen durchführen kann, und es dennoch möglich ist, die Größe einer VTableRec später zu ändern). Wenn die TMixedClass in einer anderen Bibliothek erzeugt würde, wä re das verhängnisvoll für uns, die Verfahren aus diesen vtables zu kopieren, wenn sie nicht in der gleichen Reihenfolge erzeugt wären, in der sie der SLM erwartet.
- Der SLM verwendet die Reihenfolge, die von CFront von AT&T erzeugt wird. Der Algorithmus ist folgender:
- 1) Eine Liste aller Vaterklassen in der Reihenfolge erzeugen, in der sie vereinbart wurden.
- 2) Für jeden Vater, der nicht als "virtuell" vereinbart wurde, sind alle Väter und deren Väter usw. zu prüfen. Wenn der Anwender irgendwo in der Hierarchie diesen Vater als "virtuell" findet, so ist diese Klasse aus der Liste der Väter des Anwenders zu entfernen.
- 3) Nun sind zwei Listen von Vätern zu erzeugen, eine "hasA"- Liste für virtuelle Väter und eine "isA"-Liste für nichtvirtuelle Väter. Wenn der Anwender am Anfang seiner ursprünglichen Vaterliste beginnt und wenn der Vater "virtuell" ist, ist er an den Anfang der "hasA"-Liste zu setzen, und wenn nicht, ist er an das Ende der "isA"-Liste zu setzen.
- 4) Nun ist die "hasA"-Liste zu nehmen und jede Vaterklasse auf der Liste ans Ende der "isA"-Liste zu schieben. Nun hat man eine Liste der Vaterklassen in der richtigen Reihenfolge. Nun können wir die Namen der vtables aus dieser Liste erzeugen.
- 1) Es ist eine neue Liste für vtable-Namen zu erzeugen.
- 2) Es ist eine vtable called_vtbl_ ClassName zu erzeugen, wobei die Länge des Klassennamens ist. Seine Vaterklasse ist die erste Klasse in der Vaterliste des Anwenders, wenn diese erste Klasse nicht in einem Flag als "virtuell" gekennzeichnet ist, in welchem Falle es dann keinen Vater gibt. Diese vtable ist am Ende der vtable-Liste anzufügen.
- 3) Wenn das erste in der Vaterliste des Anwenders ein virtueller Vater ist, dann muß eine weitere vtable mit dem folgenden Namen erzeugt werden:
- _vtbl_ < ParentName> _ < MyName>
- wobei < ParentName> der Name der ersten Vaters in der Liste ist. Diese vtable ist am Ende der vtable-Liste anzufügen.
- 4) Die Liste der vtables, die zu der Vaterklasse gehört, die die erste in der Liste des Anwenders ist, ist zu holen. Es ist die erste vtable in dieser Vaterliste zu überspringen.
- 5) Für jede verbleibende vtable in der Vaterklassenliste ist ein neuer vtable-Name zu erzeugen:
- _vtbl_ < ParentSubName> _ < MyName> ,
- wobei der < ParentSubName> vom Namen der Vater-VTable wie folgt abgeleitet ist:
- 1) _vtbl_ ist vom vorderen Teil des vtable-Namens wegzulassen.
- 2) Die Zahlen sind vom Endteil des vtable-Namens zu entfernen.
- 3) Die Zahlen im vorderen Teil des vtable-Namens sind zu ändern, so daß sie der Länge der neuen Zeichenkette entsprechen. Zum Beispiel wird _vtbl_7MMixin1_11TMixedClass zu _20MMixin1_TMixedClass.
- 6) Wenn der neue vtable-Name nicht bereits in der Liste des Anwenders ist, ist er am Ende der Liste anzuhängen.
- 7) Für jeden verbleibenden Vater in ihrer Vaterliste des Anwenders ist Schritt S und 6 durchzuführen (die erste vtable für die verbleibenden Väter darf nicht übersprungen werden).
- An diesem Punkt erhält man eine Liste von vtables für seine Klasse, die genau die gleiche Liste ist wie die, die das LibraryBuilder-Werkzeug des SLM erzeugt. Natürlich muß dieser Algorithmus für Compiler, die vtables mit verschiedenen Bezeichnungskonventionen erzeugen, passend modifiziert werden.
- Das folgende ist der Initialisierungscode für die Bibliothek, die erzeugt wird.
- Man beachte, daß die sekundären vtables eine 0 für den Zeiger auf die Initialisierungsfunktion haben. Der SLM nimmt an, daß die Initialisierungsfunktion für den ersten vorherigen VTableRec, der eine hat, die Initialisierung für diese VTable- Recs durchführt. Außerdem ist für alle sekundären vtables der ClientVTableRec nicht der ClientVTableRec der Klasse selbst, sondern für die Vaterklasse, die der vtable entspricht, die im VTableRec gespeichert wird, der die Klasse darstellt, in die wir das Objekt konvertieren können. Wenn wir uns beispielsweise den zweiten Aufruf an den InitIVtableRec für TMixedClass2 anschauen, dann wird &_CVRMMixin2 an den SLM übergeben. Wenn wir uns die SVR-Funktion für TMixedClass2 anschauen, so finden wir, daß _vtbl_20MMixin2_TMixedClass_12-TMixedClass2 die vtable ist, die in diesem VTableRec gespeichert ist. Diese vtable ist die vtable, die verwendet wird, wenn eine TMixedClass2 zu einem MMixin2-Objekt konvertiert wird. Man beachte jedoch, daß wir &_CVRTMixedClass als den ClientVTableRec der Vaterklasse übergeben haben. Der Grund dafür ist, daß diese vtable, obwohl sie zu dem Teil von TMixedClass2 gehört, der ein MMixin2-Objekt ist, tatsächlich von der _vtbl_7MMixin2_11TMixedClassVTable von TMixedClass geerbt ist.
- Eine gemeinsame Bibliothek bzw. Gemeinschaftsbibliothek des SLM besteht aus einer Anzahl von Betriebsmitteln, die durch einen Betriebsmittel-id und einen Codebetriebsmitteltyp verbunden sind (siehe Fig. 8). Eine beliebige Anzahl dieser Bibliotheken kann in einer einzelnen Datei abgelegt werden, solange die verwendeten Betriebsmittel-ids und die Codebetriebsmitteltypen, eindeutig sind.
- Alle Bibliotheken haben ein 'libr'-Betriebsmittel mit einem Betriebsmittel-id. Der SLM sucht alle 'libr'- Betriebsmittel in einer Bibliotheksdatei, um alle Bibliotheken in der Datei zu katalogisieren. In dem 'libr'-Betriebsmittel ist der Codebetriebsmitteltyp, der zu dieser Bibliothek gehört, definiert. Für Bibliotheksdateien mit mehreren Bibliotheken sind diese Typen normalerweise 'cd01', 'cd02', usw.
- Außerdem kann jede Bibliothek ein 'libi'-Betriebsmittel haben, daß den gleichen Betriebsmittel-id hat wie das entsprechende 'libr'-Betriebsmittel. Dieses 'libi'-Betriebsmittel enthält Information über alle gemeinsam verwendeten Klassen und Funktionssätze, die von der Bibliothek benötigt werden. Das Werkzeug CreateLibraryLoadRsrc erzeugt 'libi'- Betriebsmittel.
- Eine Bibliothek wird installiert, wenn der SLM initialisiert wird (normalerweise zur Urladezeit) oder wenn sie durch Hineinziehen (Dragging) in einen Bibliotheksordner installiert wird. Dies ist normalerweise der "Erweiterungs"- Ordner, aber zusätzliche Ordner können durch Anwendungen wie Bibliotheksordner registriert werden.
- Wenn eine Bibliothek installiert wird, wird ihr 'libr'- Betriebsmittel eingelesen vom Bibliotheksmanager. Der Bibliotheksmanager pflegt einen Katalog von Class IDs und Function-Set IDs und die Daten für jeden, die vom 'libr'-Betriebsmittel bekommt. Man beachte, daß eine Bibliotheksdatei mehr als eine Bibliothek umfassen kann, wobei dann sie mehrere 'libr'- Betriebsmittel hat.
- o Das 'libr'-Betriebsmittelformat (man beachte: die Feldanordnung LibrLine hat nicht mehr als einen Eintrag, statt dessen sind mehrere 'libr'-Betriebsmittel vorhanden.
- o 'libr'-Betriebsmittel einer ExampleLibrary
- o 'libr'-Betriebsmittel eines Mehrfachvererbungsbeispiels
- Man beachte, daß ein Sternchenzeichen '*' vor den ClassID jeder Vaterklasse gesetzt ist, die in der Klassenvereinbarung als virtuell definiert wurde.
- Es sind verschiedene Felder im 'libr'-Betriebsmittel vorhanden, die man beachten sollte.
- 1) Die Flags für das Codebetriebsmittel. Dieses Feld ist ein Bitmuster, das die Attribute der Bibliothek sowie die Bits definiert, die einschränken können, wann die Bibliothek geladen wird. Zur Bedeutung jedes der Bits siehe den späteren Abschnitt über das LibraryBuilder-Werkzeug.
- 2) Der "Binärbaum"-Typ ist in den unteren zwei Bits des zweiten Bytes des Flags codiert. Das nächste Bit zeigt an, ob der Speicher tut die Bibliothek "gehalten" werden sollte, wenn VirtualMemory verwendet wird.
- 3) Die longint, die die Binärbaumgröße festlegt. Dies ermöglicht es dem Anwender, die Größe des Binärbaums festzulegen, den die Bibliothek laden soll. Normalerweise erzeugt der SLM einen Binärbaum, der groß genug ist, um den gesamten Code der Bibliothek zu halten. Wenn man plant, Segmente manuell zu laden und zu entladen, will man möglicherweise einen kleineren Binärbaum erzeugen.
- 4) Die integer (ganze Zahl), die eine Pro-Client-Datengröße festlegt. Wenn die Bibliothek eines Anwenders Pro-Client-Daten erfordert, besorgt dies der SLM für ihn, dieser muß allerdings die Größe der erforderlichen Daten kennen. Man kann dann die GetClientData-Funktion verwenden, um eine Struktur dieser Größe für jeden Client, den man hat, zu lesen.
- 5) Die Haupt- und Nebenversionsnummern der 'libr'-Schablone. Diese sollten immer auf 0x01 für die Hauptversion und auf 0x10 für die Nebenversion gesetzt werden. Dies entspricht der 'libr'-Schablonendefinition für den SLM.
- 6) Die Versionsnummer der Bibliothek wird im Bibliotheks-id codiert.
- Bibliotheken und Clients können 'libi'-Betriebsmittel haben. Wie bereits gezeigt worden ist, muß der Betriebsmittelid des 'libi'-Betriebsmittels für die Bibliothek mit dem Betriebsmittel-id des 'libr'-Betriebsmittels übereinstimmen. Für Anwendungen und Clients muß das 'libi'-Betriebsmittel einen id haben, der 0 ist.
- Das Format des 'libi'-Betriebsmittels ist folgendes:
- Gegenwärtig ist das 'libi'-Betriebsmittel nichts anderes als A5-Distanzen zu den ClientVTableRecs, die von der Bibliothek oder dem Client verwendet werden. Dies ermöglicht es uns, daß 'libi'-Betriebsmittel zu erzeugen, indem die Speicherabbilddatei, die durch Verknüpfen der Gemeinschaftsbibliothek oder des Clients für Verweisungen auf Symbole, die die Form _CVRxxxxxxxx haben, erzeugt wird und die angezeigte A5- Distanz einfach im Betriebsmittel gespeichert wird.
- Wenn eine Bibliothek geladen wird, werden ein Sprungtabellenbetriebsmittel ('code' 0) und ein Initialisierungsbetriebsmittel ('code' 1) geladen, und der Eintrittspunkt wird aufgerufen. Die Eintrittspunktroutine initialisiert die statischen Daten für die Bibliothek und ruft dann die init v-table- Funktion auf. Die _Init VTableRecords-Funktion richtet die vtables, vtable-Datensätze (VTableRec) ein und verbindet sie mit dem internen Katalogeintrag (TClass) des Bibliotheksmanagers für jeden Funktionssatz und jede Klasse in der Bibliothek.
- Dies ist die Eintrittspunktroutine in die Bibliothek. Der LibraryBuilder-Verknüpfungsbefehl (erzeugt in SharedLibtemp.bat) verwendet die Option "-m DynamicCodeEntry", die diesen dritten Sprungtabelleneintritt durchführt (im modellfernen Fall sind die ersten beiden Einträge "leere" Einträge).
- Die "Export"-Datei definiert die Klassen und Funktionen, die zu exportieren sind. Diese Datei hat drei Hauptkomponenten: eine Library-Vereinbarung, Class-Vereinbarung und FunctionSet-Vereinbarung. Die volle Syntax für diese Vereinbarungen ist im nächsten Abschnitt beschrieben. Außerdem sind "C"- oder "C++"-Stilkommentare erlaubt sowie #include- Anweisungen. Die LibraryBuilder-Anwendung kann diese include- Dateien abtasten, um die Definitionen der mit #define defi nierten Symbole zu lernen, die Teile der Exportdefinitionen sein können.
- Eine .exp-Datei besteht aus Kommentaren #include- Direktiven, #define-Direktiven, einer Library-Vereinbarung, plus Class- und/oder FunctionSet-Vereinbarungen.
- Die Library- bzw. Bibliotheksvereinbarung definiert den ID der Gemeinschaftsbibliothek und die Version. Zusätzliche Parameter sind verfügbar, um die Bibliothek zu konfigurieren.
- Mit dieser Vereinbarung kann man den Namen einer "C"- Routine (die keine Parameter annimmt und keine Werte zurückgibt) festlegen, die unmittelbar nach dem Laden und Konfigurieren der Bibliothek aufgerufen wird. Diese Routine kann in dem ASInit-Segment sein, so daß sie aus dem Speicher entladen wird, nachdem die Bibliothek vollständig geladen ist.
- Mit dieser Vereinbarung kann man den Namen einer "C"- Routine (die keine Parameter annimmt und keinen Wert zurückgibt) festlegen, die aufgerufen wird, bevor eine Bibliothek aus dem Speicher entladen wird. Diese Routine darf nicht in dem ASInit-Segment sein, da sie nicht neu geladen werden kann.
- Dieses Flag zeigt an, daß die Segmente der Gemeinschaftsbibliothek nicht vom Client entladen werden. Der SLM löst zur Bibliotheksladezeit alle Sprungtabellenverweise zu Codeadressen auf und entfernt die Sprungtabellen aus dem Speicher. Dies ist eine Standardoptionseinstellung.
- Dieses Flag zeigt an, daß die Segmente der Gemeinschaftsbibliothek vom Client entladen werden können. Der SLM läßt zu, daß Segmente in die Gemeinschaftsbibliothek geladen und entladen werden können und behält die Sprungtabelle im Speicher.
- Dieses Flag zeigt an, daß alle Segmente der Gemeinschaftsbibliothek zur Bibliotheksladezeit geladen werden sollten. Es garantiert nicht, daß die Segmente nicht entladen werden, so daß die Sprungtabelle im Speicher aufbewahrt werden muß und Intersegmentverweisungen weiterhin auf die Sprungtabelle zeigen. "flags = !preload" wird auch unterstützt, ist jedoch der Standardoptionsfall.
- Dieses Flag zeigt an, daß der SLM alle abhängigen Klassen immer dann laden sollte, wenn diese Bibliothek geladen wird (anhand der Information im 'libr'-Betriebsmittel, das während des Aufbauprozesses erzeugt wird). Die Verwendung dieses Flags garantiert, daß alle Bibliotheken, von der Bibliothek eines Anwenders abhängig sind, vorhanden sind. Es garantiert nicht, daß genug Speicher vorhanden ist, um sie zu laden.
- Dieses Flag wirkt ebenso wie das loaddeps-Flag, aber es erzwingt, daß abhängige Bibliotheken in den Speicher geladen werden.
- Dieses Flag erzwingt, daß die Bibliothek eines Anwenders geladen bleibt. Es erfordert einen Aufruf, Bibliotheken aus der Bibliothek eines Anwenders zu entladen (UnloadLibraries), damit die Bibliothek eines Anwenders entladen wird. Es ist ein Äquivalent zum Aufruf LoadLibraries(true, true) in der InitProc des Anwenders. Es bewirkt auch, daß alle Abhängigkeiten eines Anwenders in den Speicher geladen werden (wie die "Forcedeps"-Flags).
- Dieses zeigt an, daß die Bibliothek eines Anwenders nicht registriert werden sollte, wenn sie in einem Macintosh installiert wird, der auf einem System 7.x beruht. Clients können keine Klassen oder Funktionssätze in der Bibliothek eines Anwenders sehen. Dieses Flag ist nützlich, wenn man zwei verschiedene Versionen einer Bibliothek hat, eine für das System 6.x und eine für das System 7.x.
- Dieses zeigt an, daß die Bibliothek eines Anwenders nicht registriert werden sollte, wenn sie auf einem Macintosh installiert wird, der auf dem System 6.x beruht. Clients können keine Klassen oder Funktionssätze in der Bibliothek eines Anwenders sehen. Dieses Flag ist nützlich, wenn man zwei verschiedene Versionen einer Bibliothek hat - eine für das System 6.x und eine für das System 7.x.
- Dieses zeigt an, daß die Bibliothek eines Anwenders registriert werden sollte, wenn sie auf einem Macintosh installiert wird, der mit eingeschaltetem virtuellem Speicher (VM) läuft. Clients können keine Klassen oder Funktionssätze in der Bibliothek eines Anwenders sehen. Dieses Flag ist nützlich, wenn man zwei verschiedene Versionen einer Bibliothek hat - eine für einen eingeschalteten virtuellen Speicher und eine für einen ausgeschalteten virtuellen Speicher.
- Dieses zeigt an, daß die Bibliothek eines Anwenders registriert werden sollte, wenn sie auf einem Macintosh mit ausgeschaltetem virtuellem Speicher (VM) installiert wird. Clients können keine Klassen oder Funktionssätze in der Bibliothek eines Anwenders sehen. Dieses Flag ist nützlich, wenn man zwei verschiedene Versionen einer Bibliothek hat - eine für einen eingeschalteten virtuellen Speicher und eine für einen ausgeschalteten virtuellen Speicher.
- Dieses zeigt an, daß die Bibliothek eines Anwenders registriert werden sollte, wenn sie auf einem Macintosh ohne Gleitkommaeinheit (FPU) installiert wird. Clients können keine Klassen oder Funktionssätze in der Bibliothek eines Anwenders sehen. Dieses Flag ist nützlich, wenn man zwei verschiedene Versionen einer Bibliothek hat - eine, wenn eine FPU vorhanden ist, und eine, wenn keine vorhanden ist.
- Dieses zeigt an, daß die Bibliothek eines Anwenders registriert werden sollte, wenn sie auf einem Macintosh mit einer Gleitkommaeinheit (FPU) installiert wird. Clients können keine Klassen oder Funktionssätze in der Bibliothek eines Anwenders sehen. Dieses Flag ist nützlich, wenn man zwei verschiedene Versionen einer Bibliothek hat - eine, wenn eine FPU vorhanden ist, und eine, wenn keine vorhanden ist.
- Dieses zeigt an, daß die Bibliothek eines Anwenders nur registriert werden sollte, wenn sie auf einem Macintosh mit den festgelegten Prozessoren installiert wird. Man kann mehr als einen Prozessor festlegen. Beispielsweise bewirkt "Flags = mc68000, mc68020", daß die Bibliothek eines Anwenders nur auf den Prozessoren 68000 oder 68020 registriert wird.
- Dieses zeigt an, daß die Bibliothek eines Anwenders nicht registriert werden sollte, wenn sie auf einem Macintosh installiert wird, der nicht einer der festgelegten Prozessoren ist. Man kann mehr als einen Prozessor festlegen. Beispielsweise bewirkt "Flags = !mc68000, !mc68020", daß die Bibliothek eines Anwenders nur auf einem Macintosh mit einem Prozessor 68030 oder höher registriert wird. Es ist falsch, negierte ("!"-) Angaben mit nichtnegierten Angaben zu mischen (nämlich Flags = mc68000, !mc68020).
- Diese Vereinbarung definiert den ID der Bibliothek. Der Bibliotheks-ID hat normalerweise die Form "xxxx:yyyy$Name". Diese ID-Zeichenkette ist eine angeführte Zeichenkette, aber sie kann mit #define definierte Konstante als Teil ihrer Definition enthalten, solange man die Dateien, die #define- Vereinbarungen enthalten, die die Konstanten auflösen, mit #include einbezieht.
- Diese Vereinbarung definiert die Version der Bibliothek. Die Versionsnummer hat die Form einer normalen Apple- Versionsnummer: #.#.[#], entweder gefolgt von nichts oder von [dabf]#, um den Freigabestatus anzuzeigen. Zum Beispiel: 1.0b2 oder 1.1.2d5. Dies kann ein mit #define definiertes Symbol sein.
- Diese Vereinbarung zeigt an, daß alle "neuen" Operationen, die in der Bibliothek erfolgen, den Pool des Clients verwenden sollten. Dies ist die Standardoption, wenn nichts festgelegt wird. Sie ist äquivalent mit den useclientpool-Optionen in älteren Versionen des SLM.
- Diese Vereinbarung zeigt an, daß alle "neuen" Operationen, die in der Bibliothek erfolgen, den lokalen Pool verwenden sollten.
- Dadurch wird der SLM informiert, wohin man seine Bibliothek in den Speicher geladen haben möchte. Normalerweise sollte man dieses Attribut nur festlegen, wenn man einen sehr guten Grund hat. Wenn die Bibliothek jedoch unter einem virtuellen Speicher laufen muß und nicht im Speicher verschoben werden kann (z. B. ein Netztreiber), kann man das ",hold"- Attribut festlegen, um den SLM zu informieren, daß man den Speicher braucht, in den die Bibliothek geladen wird, damit sie im virtuellen Speicher "gehalten" werden kann. Man kann auch als Option die Größe des Binärbaums festlegen, in den die Bibliothek geladen werden soll (diese Option hat nur Sinn bei default oder temp).
- Dadurch wird der SLM informiert, daß man statische Pro- Client-Daten braucht. Man kann entweder eine Anzahl von Bytes oder den Namen einer Struktur festlegen. Immer wenn man Get- ClientData aufruft, wird einem eine Struktur mit der festgelegten Größe zurückgegeben. Wenn die Struktur das erste Mal für einen gegebenen Client erzeugt wird, wird sie auf null gesetzt. Nach dem ersten Mal erhält man die Struktur entsprechend seinem aktuellen Client zurück. Wenn man den Strukturna men festlegt, muß die Objektdatei die Typinformation verfügbar haben, um die Größe der Struktur zu bestimmen, oder es wird ein Fehler erzeugt.
- Eine volle Class- bzw. Klassenvereinbarung ist folgende:
- Alle Felder außer das < ClassName> sind optional.
- Die kleinste Klassenvereinbarung ist lediglich:
- Class < ClassName> ;
- Der id der Klasse muß als Konstante der Form k< ClassName> ID mit #define definiert sein. Es ist optional (aber eine sehr gute Idee), wenn ein Klassen-ID mit einem ", " abschließt, gefolgt von der Versionsnummer der Klasse, besonders wenn die Klasse mit der NewObject-Funktion des SLM instanziert werden kann. Dadurch wird verhindert, daß die Clients eines Anwenders unbeabsichtigt eine falsche Version der Klasse bekommen.
- Dieses ist der Name der Klasse, den man exportieren will.
- Diese Vereinbarung definiert eine Version der Klasse. Die Versionsnummer hat die Form der normalen Apple- Versionsnummern: #.#[.#]. Diese Versionsnummer kann die Extra- Ereigabeinformation (wie etwa b2) haben. Die Versionsnummer kann aber auch von zwei Versionsnummern dargestellt werden, die entweder durch drei Punkte (...) oder durch eine Ellipsenzeichen (option-; ) getrennt sind. Dies zeigt die niedrigste Versionsnummer der Klasse, mit der diese Klasse rückwärtskompatibel ist, und die aktuelle Versionsnunmer der Klasse an. Wenn man keine Versionsnummer festlegt, dann wird, wenn der Class-ID der Klasse eine Versionsnummer hat, diese benutzt. Andernfalls wird die Versionsnummer, die in der "Library"- Vereinbarung festgelegt ist, angenommen. Dies kann ein mit #define definiertes Symbol sein.
- Dieses Flag legt fest, daß Clients die Klasse nach dem Class-ID mit der NewObject-Routine erzeugen können. Ein schwerer Fehler zur Aufbauzeit tritt auf, wenn dieses Flag gesetzt ist, man jedoch keinen Standardoptionskonstruktor für seine Klasse hat (ein Standardoptionskonstruktur ist einer, der keine Argumente annimmt), die Klasse abstrakt ist (ein "rein virtuelles" Verfahren hat) oder die Klassengröße nicht aus einer Symbolinformation in der Objektdatei bestimmt werden kann.
- Dieses Flag legt fest, daß eine Instanz der Klasse immer dann erzeugt werden sollte, wenn eine Urladung des Systems erfolgt. Ein schwerer Fehler zur Aufbauzeit tritt auf, wenn dieses Flag gesetzt ist, man jedoch keinen Standardoptionskonstruktor für seine Klasse hat (ein Standardoptionskonstruktor ist einer, der keine Argumente annimmt) oder die Klasse abstrakt ist (ein "rein virtuelles" Verfahren hat). Wenn das Flag gesetzt wird, wird das newobject-Flag automatisch gesetzt.
- Dieses Flag legt fest, daß keine Verfahren dieser Klasse exportiert werden sollen. Nur mit NewObject kann ein Client eine Klasse verwenden, wenn dieses Flag gesetzt ist und man keine Konstruktoren im exports=-Teil exportiert, und diese können nur virtuelle Funktionen in der Klasse aufrufen, wenn man nicht explizit Verfahren exportiert (siehe exports= unten).
- Dieses Flag legt fest, daß keine virtuellen Verfahren dieser Klasse zu exportieren sind. Für die Zwecke der Konsistenz im SLM wird der Destruktor einer Klasse NICHT als virtu elles Verfahren angesehen, auch wenn er so definiert wurde. Man kann bestimmte virtuelle Funktionen mit der exports=- Klausel unten explizit exportieren.
- Dieses Flag legt fest, daß keine nichtvirtuellen Methoden dieser Klasse zu exportieren sind. Dies schließt Konstruktoren und Destruktoren für die Klasse ein. Nur mit NewObjekt kann ein Client die Klasse verwenden, wenn dieses Flag gesetzt ist und man keine Konstruktoren im exports=-Teil exportiert.
- Damit wird eine kommagetrennte Liste von Verfahren vereinbart, die man aus der Klasse exportieren will. Es wird normalerweise verwendet, um "noExports"-, "noMethodExports"- oder "noVirtualExports"-Flags für einzelne Verfahren festzulegen. Man braucht lediglich den Funktionsnamen festzulegen, und wenn es eine Pascalsche Funktion ist, muß man das Schlüsselwort "pascal" vor den Funktionsnamen setzen. Wie bei C++, so betrachtet der SLM ALLE Varianten einer Elementfunktion als die gleiche Funktion und exportiert sie alle. Um Operatoren zu exportieren, verwendet man die C++-Syntax (z. B. Operator+= ). Um Konstruktoren zu exportieren, verwendet man den Namen der Klasse, und um Destruktoren zu exportieren, verwendet man ~< Name of Class> .
- Damit wird eine kommagetrennte Liste von Funktionen vereinbart, die man aus der Klasse exportieren will. Man muß lediglich den Funktionsnamen festlegen, und wenn es eine Pascalsche Funktion ist, muß man das Schlüsselwort "pascal" vor den Funktionsnamen setzen. Wie bei C++, so betrachtet der SLM ALLE Varianten einer Elementfunktion als die gleiche Funktion und exportiert keine von ihnen. Man kann exports= und dontexport = nicht für die gleiche Klasse verwenden.
- Damit wird eine kommagetrennte Liste von Verfahren vereinbart, die man privat aus der Klasse exportieren will. Alle in dieser Liste festgelegten Verfahren werden exportiert, gehen jedoch in eine getrennte Client-Objekt-Datei ein (die durch die -privateNear- und/oder -privateFar-Befehlszeilenschalter zum LibraryBuilder definiert wird).
- Damit wird vereinbart, daß alle Verfahren, die exportiert werden können, privat exportiert werden sollten. Wenn man noMethodExports gesetzt hat, dann werden alle virtuellen Verfahren privat exportiert, die entweder durch die exports=- Klausel nicht explizit öffentlich exportiert werden oder durch eine dontexport=-Klausel spezifisch vom Exportieren ausgeschlossen sind. Wenn man novirtualExports gesetzt hat, dann werden alle nichtvirtuellen Verfahren privat exportiert, die durch die exports=-Klausel entweder nicht explizit öffentlich exportiert werden oder durch eine dontexport=-Klausel spezifisch vom Exportieren ausgeschlossen sind. Wenn man keines der beiden Flags gesetzt hat, dann werden alle Verfahren der Klasse privat exportiert, die entweder durch die exports=-Klausel nicht explizit öffentlich exportiert werden oder durch eine dontexport=-Klausel spezifisch vom Exportieren ausgeschlossen sind. Es ist ein Fehler, diesen Schalter zu verwenden, wenn das noExports-Flag gesetzt ist. Die FunctionSet-Vereinbarung
- Wenn ein Funktionssatz keine exports=-Klausel und keine dontexport=-Klausel hat, werden alle globalen Funktionen (die keine Verfahren einer C++-Klasse sind) exportiert (vorbehaltlich irgendwelcher Einschränkungen, die durch die private=- Klausel gesetzt werden - siehe unten). Wenn Mehrfachfunktionssätze in einer Bibliothek vorhanden sind, kann nur einer von ihnen in diesen beiden Klauseln fehlen. Der Funktionssatz, der in beiden Klauseln fehlt, exportiert alle globalen Funktionen (die nicht Verfahren einer C++-Klasse sind), die von keinem anderen der Funktionssätze in der Bibliothek exportiert werden.
- Damit wird ein eindeutiger Name für den Funktionssatz eines Anwenders beim Verknüpfen erzeugt.
- Diese Vereinbarung definiert den classID des Funktionssatzes. Ein classID hat normalerweise die Form "xxxx:yyyy$SomeName". Diese ID-Zeichenkette ist eine angeführte Zeichenkette, sie kann jedoch mit #define definierte Konstante als Teil ihrer Definition enthalten, solange man mit #include die Dateien einbezieht, die die # define-Vereinbarungen enthalten, die die Konstanten auflösen. Wenn man keine "id="-Vereinbarung einbezieht, wird angenommen, daß ein #define, das in den einbezogenen Dateien vorhanden ist, deren Name k< functionSetName> ID entspricht, der classID der Klasse ist. Ein Fehler tritt zur Aufbauzeit auf, wenn die classID der Klasse nicht bestimmt werden kann.
- Diese Vereinbarung definiert einen Interface- bzw. Schnittstellen-ID für den Funktionssatz. Sie hat das gleiche Format wie alle anderen ClassIDs. Durch Definition eines Schnittstellen-ClassID kann man die FunctionSetInfo-Verfahren des SLM verwenden, um alle Funktionssätze zu finden, die den gleichen Schnittstellen-ID hat. Mit gewisser Wahrscheinlichkeit exportieren alle Funktionssätze mit dem gleichen Schnittstellen-ID die gleiche Funktionalität, entweder nach dem Namen oder nach dem Index. Dadurch wird eine Art von objektorientierter Fähigkeit für normale Funktionen bereitgestellt.
- Diese Vereinbarung definiert die Version des Funktionssatzes. Die Versionsnummer hat die Form der normalen Apple- Versionsnummer: #.#.[#]. Die Versionsnummer kann keine Extra- Freigabeinformation (wie etwa b2) haben. Die Versionsnummer kann durch zwei Versionsnummern dargestellt werden, die entwe der durch drei Punkte (...) oder durch eine Ellipsenzeichen (option-;) getrennt sind. Dies zeigt die niedrigste Version des Funktionssatzes, mit dem dieser Funktionssatz rückwärtskompatibel ist, und die aktuelle Versionsnummer des Funktionssatzes an. Nichts erfolgt mit dieser Information in Version 1.0 des SLM, aber künftige Versionen werden diese Information nutzen. Wenn man keine Versionsnummer festlegt, wird die Versionsnummer angenommen, die in der "Library"-Vereinbarung festgelegt ist. Dies kann ein mit #define definiertes Symbol sein.
- Damit wird eine kommagetrennte Liste von Funktionen vereinbart, die man in diesem Funktionssatz exportieren will. Man muß nur den Funktionsnamen festlegen, und wenn es eine Pascalsche Funktion ist, muß man das Schlüsselwort "pascal" vor den Funktionsnamen setzen. Wie bei C++, betrachtet der SLM ALLE Varianten einer Funktion als die gleiche Funktion und exportiert sie alle (wenn man nicht den -c-Schalter in der BuildSharedLibrary-Befehlszeile verwendet). Wenn man ein C++- Klassenverfahren exportiert, muß man vor den Verfahrensnamen < ClassName> :: setzen. Bei einem C++-Klassenverfahren wird der -c-Schalter ignoriert, und alle Varianten des Verfahrens werden exportiert. Um C++-Operatorüberlastungen zu exportieren, benutzt man die C++-Syntax (z. B. Operator+= ). Um Konstruktoren zu exportieren, benutzt man < ClassName> ::< ClassName> , und um Destruktoren zu exportieren, benutzt man < ClassName> ::~< ClassName> . Bestimmte spezielle Schlüsselwörter sind in dieser Klausel verfügbar. Diese sind:
- 1) static < ClassName> - alle statischen Verfahren der festgelegten Klasse werden exportiert.
- 2) class < ClassName> - alle nichtstatischen Verfahren der festgelegten Klasse werden exportiert.
- 3) extern < FunctionName> - die festgelegte Funktion wird nach dem Namen exportiert.
- 4) pascal < FunctionName> - die festgelegte Funktion ist eine Pascalsche Funktion. Das Schlüsselwort "pascal" kann bei Bedarf mit dem Schlüsselwort "extern" kombiniert werden.
- Damit wird eine kommagetrennte Liste von Funktionen vereinbart, die man in diesen Funktionssatz exportieren will. Diese Klausel hat die gleiche Syntax wie die "exports="- Klausel, außer daß die Schlüsselwörter "static", "class" und "extern" nicht gültig sind.
- Damit wird eine kommagetrennte Liste von Verfahren vereinbart, die man aus dem Funktionssatz privat: exportieren will. Alle in dieser Liste festgelegten Verfahren werden exportiert, gehen jedoch in eine getrennte Client-Objekt-Datei ein (die durch die -privateNear- und/oder -privateFar- Befehlszeilenschalter zum LibraryBuilder definiert wird). Wenn man keine exports=- oder dontExport=-Klausel definiert hat, dann werden alle anderen Funktionen öffentlich exportiert.
- Damit wird vereinbart, daß alle Funktionen, die exportiert werden, privat exportiert werden sollten. Wenn man keine exports=- oder dontExport=-Klausel definiert hat, dann werden alle Funktionen privat exportiert. Wenn man eine exports=- Klausel hat, dann werden die vereinbarten Funktionen öffentlich exportiert, und alle anderen werden privat exportiert. Wenn man eine dontExport=-Klausel hat, dann werden die vereinbarten Funktionen nicht exportiert, und alle anderen werden privat exportiert. Wenn man beide Klauseln hat, dann werden die in der dontExport=-Klausel nicht exportiert, die in der exports=-Klausel werden öffentlich exportiert, und alle anderen werden privat exportiert.
- Demzufolge stellt die Erfindung eine Systemerweiterung bereit, die einer Computersystemarchitektur dynamisches Verknüpfen und dynamisches Laden durch die Verwendung von Gemeinschaftsbibliotheken ermöglicht. Durch den Gemeinschaftsbibliotheksmanager kann man fast jeden Code in eine Gemeinschaftsbibliothek verwandeln, ohne daß man seine Betriebsmittel modifiziert und ohne daß man zusätzlichen Code schreibt. Man schreibt den Code, der in die Gemeinschaftsbibliothek eingeht, in seiner gewählten Betriebsmittelsprache oder in Assembler und ruft ihn auch aus irgendeiner dieser Sprachen auf. Außerdem ermöglicht das System das Aufrufen von virtuellen Funktionen in einer C++-Klasse in einer Gemeinschaftsbibliothek ohne zusätzlichen Organisationsaufwand.
- Dieses System ist für C++-Klassen besonders effektiv. Objektorientierte Sprachen wie C++ geben Programmierern die Möglichkeit zum modularen Entwurf mit spezifischer Codewiederverwendung und bieten bessere Möglichkeiten des Zusammensetzens von Programmen. Das Konzept der Codewiederverwendung und Modularität wird heute in vielen Implementationen voll realisiert. Ein allgemeiner Mechanismus für Laufzeitteilung von Klassen ermöglicht es den Entwicklern, die objektorientierten Vorteile von C++ besser auszunutzen. Echte Codeteilung und -wiederverwendung werden möglich. Verbesserungen der Implementationen von Klassen können von allen Anwendungen unmittelbar genutzt werden, ohne die Anwendung, die die Klasse verwendet, neu aufzubauen. Man kann eine Klasse erzeugen, die sich von einer Basisklasse ableitet, die in einer Gemeinschaftsbibliothek ist, die zu noch einem anderen Begriff führt, der dynamischen Vererbung. Tatsächlich kann die Unterklasse selbst in einer Gemeinschaftsbibliothek sein.
- Somit ist die Erfindung besonders für Anwendungen geeignet, die die Möglichkeit haben wollen, Module zu einer späteren Zeit hinzuzufügen. Wenn die Module in Gemeinschaftsbibliotheken abgelegt werden, kann die Anwendung prüfen, welche Module vorhanden sind, und wählen, welche Module sie verwenden will.
- Außerdem sind Werkzeuge, wie etwa Rechtschreibkorrekturprogramme, für erfindungsgemäße Gemeinschaftsbibliotheken gut geeignet. Wenn alle Rechtschreibkorrekturprogramme eine gemeinsame Schnittstelle verwenden, kann die Anwendung wählen, welches Rechtschreibkorrekturprogramm sie verwenden will. Außerdem kann das Rechtschreibkorrekturprogramm von mehr als einer Anwendung gleichzeitig verwendet werden.
- Im allgemeinen ist jeder Code, dessen gemeinsame Verwendung zwischen einer oder mehreren Anwendungen gewünscht wird, ein Kandidat für eine Gemeinschaftsbibliothek. Dies ist besonders nützlich für große Softwarefirmen, die viele Anwen dungen verkaufen, die einen bestimmten gemeinsamen Code enthalten. Der Gemeinschaftsbibliotheksmanager macht es leicht, diesen Code gemeinsam zu benutzen. Beispielsweise könnte ein Textverarbeitungsprogramm einen Teil der Graphikfähigkeiten eines Graphikprogramms nutzen wollen. Solche Fähigkeiten könnten in Gemeinschaftsbibliotheken abgelegt werden und erfindungsgemäß dynamisch verknüpft werden.
- Bestimmte Schlüsselmerkmale des Gemeinschaftsbibliotheksmanagers sind die folgenden.
- Gemeinschaftsbibliotheken werden mit Clients zur Laufzeit geladen und verknüpft (und entladen, wenn keine Clients sie verwenden). Das Laden erfolgt bei Bedarf, nicht in der Anlaufzeit. Aber der Anwender kann erzwingen, daß Bibliotheken in der Anlaufzeit geladen werden, um sicher zu sein, daß sie verfügbar sind.
- Gemeinschaftsbibliotheksdateien können in Erweiterungsordnern hineingezogen (Dragging in) oder aus diesen herausgezogen (Dragging out) werden, ohne daß eine neue Urladung erfolgen muß, wenn man Gemeinschaftsbibliotheken verwenden will.
- Eine Anwendung kann durch Überprüfung feststellen, daß ein Satz von Klassen oder Funktionen, die für eine entsprechende Operation der Anwendung erforderlich ist, verfügbar ist. Die erforderlichen Gemeinschaftsbibliotheken können dann geladen werden, oder das Laden kann verzögert werden, bis der Code benötigt wird.
- Um zu garantieren, daß eine Bibliothek verfügbar ist, wenn sie benötigt wird, kann eine Gemeinschaftsbibliothek so eingestellt werden, daß sie zur Urladezeit vorabgeladen wird, oder sie kann von einem Client explizit geladen werden, und zwar nach der Urladezeit, aber bevor irgendwelche Klassen oder Funktionen tatsächlich verwendet werden.
- Der Gemeinschaftsbibliotheksmanager ermöglicht dynamisches Hochleistungsladen und -verknüpfen von Funktionssätzen und Klassen, Hochleistungsaufbau, -verwendung und -abbau von Objekten. In C++ wird ein Verfahren oder eine virtuelle Funktion nur über einen einzigen Umweg, über eine Tabelle von Zeigern auf Funktionsimplementationen (die als v-table oder virtuelle Funktionstabelle bezeichnet wird) aufgerufen. Eine dynamisch verknüpfte Funktion oder Prozedur wird "durch Einschnappen verknüpft", was bedeutet, daß der Bindungsaufwand nur einmal auftritt, woraufhin die Zieladresse im Client cachegespeichert wird (die Verknüpfung "einschnappt").
- Dieser Aufrufmechanismus ist viel effizienter als die Macintosh Device Manager-Zuteilung, die von Gerätetreibern verwendet wird, oder der A trap plus selector code-Mechanismus, der von eigenständigen Codebetriebsmitteln auf dem Macintosh verwendet wird (z. B. CDEFs, WDEFs und die Communications Toolbox). Andere Mechanismen, z. B. IPC-Meldungen, sind im Vergleich auch ineffizient und für eine zeitkritische Verwendung (wie gefordert durch Hochleistungsnetzprotokolle oder andere Hochleistungsgerätetreiber) nicht gut geeignet.
- Eine Klasse kann von einer Klasse erben, die nicht in der gleichen Gemeinschaftsbibliotheksdatei ist. Dies bedeutet auch, daß der Entwickler eine Klasse erzeugen kann, die von einer Klasse eines anderen Entwicklers erbt. Die neue Unterklasse kann entweder in einer anderen Gemeinschaftsbibliothek oder in dem Anwendungscode sein.
- Wenn ein Objekt erzeugt wird, kann man es dynamisch nach dem Namen erzeugen. Dadurch kann eine Anwendung Objekte von Klassen erzeugen, die sie niemals vorher gesehen hat. Im allgemeinen sind diese Objekte Unterklassen einer Klasse, die die Anwendung nicht kennt.
- Ein Client kann zur Laufzeit durch Überprüfung feststellen, daß eine gegebene Klasse von einer bestimmten Basisklasse abgeleitet ist oder daß ein Objekt von einer bestimmten Basisklasse stammt. Dynamische Klassenerzeugung und Klassenüberprüfung werden zusammen verwendet.
Claims (20)
1. Vorrichtung zur Verwaltung von Codebetriebsmitteln
zur Verwendung durch Client-Anwendungen (17) in einem
Computer, wobei der Computer einen internen Speicher (16) hat, der
mindestens eine Client-Anwendung speichert, mit:
einem Betriebsmittelsatzkatalog (30-42), der im
internen Speicher gespeichert ist, wobei der
Betriebsmittelsatzkatalog mehrere Funktionssätze von Elementfunktionen durch
entsprechende Funktionssatzbezeichner identifiziert und
Satzdatensätze (33) speichert, die Elementfunktionen in
entsprechenden Sätzen kennzeichnen;
einer Zuteilmaschine (91, 92) im internen Speicher, die
mit einer Client-Anwendung verknüpft ist, um einen bestimmten
Funktionssatzbezeichner zu liefern, als Antwort auf einen
Aufruf durch die Client-Anwendung einer bestimmten
Elementfunktion, die ein Element eines entsprechenden Funktionssatzes ist,
der durch den bestimmten Funktionssatzbezeichner identifiziert
wird;
einer Nachschlagmaschine (93) im internen Speicher, die
mit dem Betriebsmittelsatzkatalog und der Zuteilmaschine
gekoppelt ist und auf den bestimmten Funktionssatzbezeichner
anspricht, um einen Satzdatensatz für den entsprechenden
Funktionssatz im Betriebsmittelsatzkatalog nachzuschlagen; und
einer Verknüpfungsmaschine (94) im internen Speicher,
die mit der Zuteilmaschine gekoppelt ist, um clie bestimmte
Elementfunktion an die Client-Anwendung als Antwort auf den
Satzdatensatz zurückzugeben.
2. Vorrichtung nach Anspruch 1, ferner mit:
einer Bibliothek (203-223) von Funktionssätzen, die im
Speicher gespeichert sind, wobei Funktionssätze in der
Bibliothek Funktionssatzbezeichner haben und Elementfunktionen
aufweisen.
3. Vorrichtung nach Anspruch 1, ferner mit einem
Zuteildatensatz (53), der mit der Client-Anwendung im internen
Speicher verknüpft ist und den Funktionssatzbezeichner für
einen Funktionssatz speichert, den die Client-Anwendung
verwendet.
4. Vorrichtung nach Anspruch 1, wobei mehrere
Funktionssätze mindestens einen Funktionssatz aufweisen, der eine
Klasse kennzeichnet.
5. Vorrichtung nach Anspruch 4, wobei mindestens ein
Funktionssatz, der eine Klasse kennzeichnet, eine
Konstruktorfunktion und eine Destruktorfunktion aufweist.
6. Vorrichtung nach Anspruch 4, wobei mindestens ein
Funktionssatz, der eine Klasse kennzeichnet, eine virtuelle
Funktion in der Klasse aufweist.
7. Vorrichtung nach Anspruch 4, wobei mindestens ein
Funktionssatz, der eine Klasse kennzeichnet, eine
Konstruktorfunktion, eine Destruktorfunktion, eine virtuelle Funktion und
eine nichtvirtuelle Funktion aufweist.
8. Vorrichtung nach Anspruch 3, wobei der
Zuteildatensatz einen Satzverknüpfungscachespeicher aufweist, um einen
Verknüpfungszeiger zu dem Funktionssatz zu speichern, der die
bestimmte Elementfunktion aufweist;
die Verknüpfungsmaschine einen Code aufweist, um den
Verknüpfungszeiger an den Satzverknüpfungscachespeicher zu
liefern, als Antwort auf die Rückgabe der bestimmten
Elementfunktion an die Client-Anwendung und
die Zuteilmaschine eine Routine aufweist, die im
Satzverknüpfungscachespeicher einen cachegespeicherten
Verknüpfungszeiger zu dem Funktionssatz sucht und den
cachegespeicherten Verknüpfungszeiger an die Verknüpfungsroutine nach
einem Aufruf an die Elementfunktion im Funktionssatz der
bestimmten Elementfunktion zurückgibt.
9. Vorrichtung nach Anspruch 8, ferner mit
einer Bibliothek (203-223) von Funktionssätzen, die im
Speicher gespeichert sind, wobei Funktionssätze in der
Bibliothek Funktionssatzbezeichner haben und Elementfunktionen
aufweisen; und
wobei den Funktionssätzen Versionsnummern (220)
entsprechend einem Standardprotokoll zugeordnet werden und der
Zuteildatensatz ferner Versionsinformation aufweist, die mit
der Client-Anwendung verknüpft ist und eine minimale
Versionsnummer (221) anzeigt, die von der Client-Anwendung für den
Funktionssatz der bestimmten Elementfunktion unterstützt wird;
die Bibliothek eine Versionsnummer (214) für die
entsprechenden Funktionssätze aufweist und
die Verknüpfungsmaschine einen Code aufweist, der auf
die Versionsinformation im Zuteildatensatz und die
Versionsnummer in der Bibliothek anspricht, um sicherzustellen, daß
die Client-Anwendung eine Version des Funktionssatzes der
bestimmten Elementfunktion unterstützt.
10. Vorrichtung nach Anspruch 1, ferner mit:
einer Bibliothek (203-223) von Funktionssätzen, die im
Speicher gespeichert sind, wobei Funktionssätze in der
Bibliothek Funktionssatzbezeichner haben und Elementfunktionen
aufweisen; und
wobei die Verknüpfungsmaschine aufweist:
einen Katalog im internen Speicher, der Funktionssätze
aufführt, die zum Verknüpfen verfügbar sind; und
eine Registrierroutine im Speicher, die Funktionssätze
in der Bibliothek in den Katalog einfügt, als Antwort auf eine
Aufforderung, die Bibliothek zum Verknüpfen verfügbar zu
machen, und die Funktionssätze in der Bibliothek aus dem Katalog
entfernt, als Antwort auf eine Aufforderung, die Bibliothek
zum Verknüpfen nichtverfügbar zu machen.
11. Vorrichtung nach Anspruch 1, ferner mit:
einer Bibliothek (203-223) von Funktionssätzen, die im
Speicher gespeichert sind, wobei Funktionssätze in der
Bibliothek Funktionssatzbezeichner haben und Elementfunktionen
aufweisen; und
wobei die Verknüpfungsmaschine aufweist:
einen Katalog im internen Speicher, der Funktionssätze
aufführt, die zum Verknüpfen verfügbar sind; und
eine Registrierroutine, die während der Laufzeit der
Client-Anwendung ausführbar und im Speicher ist und die
Funktionssätze in der Bibliothek in den Katalog einfügt, als
Ant
wort auf eine Aufforderung, die Bibliothek zum Verknüpfen
verfügbar zu machen, und die Funktionssätze in der Bibliothek aus
dem Katalog entfernt, als Antwort auf eine Aufforderung, die
Bibliothek zum Verknüpfen nichtverfügbar zu machen.
12. Vorrichtung nach Anspruch 1, wobei die
Zuteilmaschine aufweist:
einen Zuteildatensatz (53), der mit dem Client
verknüpft ist und der den bestimmten Funktionssatzbezeichner
speichert; und
eine Zuteilroutine, die mit dem Zuteildatensatz und der
Nachschlagmaschine verknüpft ist, als Antwort auf einen
Aufruf, den bestimmten Funktionssatzbezeichner an die
Nachschlagmaschine zu liefern.
13. Vorrichtung nach Anspruch 12, wobei der
Zuteildatensatz einen Satzverknüpfungscachespeicher aufweist, um einen
Verknüpfungszeiger zu dem Satzdatensatz für den Satz von
Funktionen zu speichern, der die bestimmte Elementfunktion
aufweist;
die Verknüpfungsmaschine eine Routine aufweist, um den
Verknüpfungszeiger an den Satzverknüpfungscachespeicher zu
liefern, als Antwort auf die Rückgabe der bestimmten
Elementfunktion an den Client; und
die Zuteilmaschine eine Routine aufweist, die im
Satzverknüpfungscachespeicher einen cachegespeicherten
Verknüpfungszeiger zu dem Satzdatensatz sucht und den Satzdatensatz
an die Verknüpfungsmaschine zurückgibt, als Antwort auf den
cachegespeicherten Verknüpfungszeiger nach einem Aufruf an eine
Elementfunktion im Funktionssatz der bestimmten
Elementfunktion.
14. Vorrichtung nach Anspruch 13, wobei den
Satzdatensätzen für Funktionssätze laufende Nummern zugeordnet werden,
wenn die Funktionssätze im internen Speicher geladen werden,
und der Zuteildatensatz ferner eine laufende Nummer aufweist,
die mit dem Client verknüpft ist und die eine laufende Nummer
des entsprechenden Funktionssatzes anzeigt, wenn der
Satzverknüpfungscachespeicher gefüllt ist,
der Satzverknüpfungscachespeicher einen Zeiger zu einer
Verknüpfungsstruktur im internen Speicher speichert und die
Verknüpfungsstruktur einen Zeiger zu einem Satzdatensatz mit
dem bestimmten Funktionssatzbezeichner des Satzdatensatzes
aufweist und
die Verknüpfungsmaschine aufweist: eine Routine, die
auf die laufende Nummer im Satzdatensatz und die laufende
Nummer im Zuteildatensatz anspricht, um die Gültigkeit des
Satzverknüpfungscachespeichereintrags sicherzustellen, und eine
Routine zur Löschung der Verknüpfungsstruktur, wenn der
entsprechende Funktionssatz entladen wird.
15. Vorrichtung nach Anspruch 1, wobei der
Satzdatensatz einen Verwendungszählerdatensatz aufweist lind die
Verknüpfungsmaschine eine Routine aufweist, um den
Verwendungszähler zu inkrementieren, wenn eine. Client-Anwendung mit dem
Funktionssatz entsprechend dem Satzdatensatz gebunden wird,
und den Verwendungszähler zu dekrementieren, wenn die Client-
Anwendung den Funktionssatz entsprechend dem Satzdatensatz
entläßt.
16. Vorrichtung nach Anspruch 1, wobei der zumindest
eine Funktionssatz, der eine Klasse kennzeichnet, eine
Konstruktorfunktion und eine Destruktorfunktion aufweist und der
Satzdatensatz ferner ein Verwendungszählerfeld aufweist;
die Verknüpfungsmaschine eine Routine aufweist, um den
Verwendungszähler zu inkrementieren, wenn eine Client-
Anwendung eine Konstruktorfunktion für eine Klasse
entsprechend dem Satzdatensatz aufruft, und den Verwendungszähler zu
dekrementieren, wenn eine Client-Anwendung eine
Destruktorfunktion für eine Klasse entsprechend dem Satzdatensatz
aufruft; und
ferner mit einer Maschine, die auf die
Verwendungszähler in den Satzdatensätzen anspricht und die entsprechende
Funktionssätze aus einem internen Speicher entläßt, wenn der
Verwendungszähler null wird.
17. Vorrichtung nach Anspruch 1, ferner mit:
einer Registrierroutine im Speicher, die eine
Bibliothek von Funktionssätzen in den Betriebsmittelsatzkatalog
einfügt, als Antwort auf eine Aufforderung, die Bibliothek zum
Verknüpfen verfügbar zu machen, und die Funktionssätze in der
Bibliothek aus dem Betriebsmittelkatalog entfernt, als Antwort
auf eine Aufforderung, die Bibliothek zum Verknüpfen
nichtverfügbar zu machen.
18. Vorrichtung nach Anspruch 1, ferner mit:
einer Registrierroutine, die während der Laufzeit der
Client-Anwendung ausführbar und im Speicher ist und die eine
Bibliothek von Funktionssätzen in den
Betriebsmittelsatzkatalog einfügt, als Antwort auf eine Aufforderung, die Bibliothek
zum Verknüpfen verfügbar zu machen, und die Funktionssätze in
der Bibliothek aus dem Betriebsmittelsatzkatalog entfernt, als
Antwort auf eine Aufforderung, die Bibliothek ztim Verknüpfen
nichtverfügbar zu machen.
19. Vorrichtung nach einem der vorhergehenden
Ansprüche, ferner mit:
einer Bibliothek (203-223) von Funktionssätzen, die im
Speicher gespeichert sind, wobei Funktionssätze in der
Bibliothek Funktionssatzbezeichner haben und Elementfunktionen
aufweisen; und
wobei der Betriebsmittelsatzkatalog Funktionssätze in
der Bibliothek durch entsprechende Funktionssatzbezeichner
identifiziert;
die Zuteilmaschine aufweist
einen Zuteildatensatz (53), der mit dem Client
verknüpft ist und der den bestimmten Funktionssatzbezeichner
speichert,
einen Funktionsverknüpfungscachespeicher, der mit dem
Client verknüpft ist, um einen Verknüpfungszeiger zu der
bestimmten Elementfunktion zu speichern;
einen Satzverknüpfungscachespeicher, der mit dem Client
verknüpft ist, um einen Verknüpfungszeiger zu dem
Satzdatensatz für den Satz von Funktionen zu speichern, der die
bestimmte Elementfunktion aufweist;
eine Zuteilroutine, die mit dem Zuteildatensatz, dem
Funktionsverknüpfungscachespeicher, dem
Satzverknöpfungscachespeicher und der Nachschlagmaschine verknüpft ist und die auf
den Aufruf anspricht, die bestimmte Elementfunktion zu
liefern, wenn der Funktionsverknüpfungscachespeicher gültig ist,
den Satzdatensatz zu liefern, wenn der
Satzverknüpfungscachespeicher gültig ist, und den bestimmten
Funktionssatzbezeich
ner zu liefern, wenn weder der
Funktionsverknüpfungscachespeicher noch der Satzverknüpfungscachespeicher gültig ist; und
wobei die Verknüpfungsmaschine die bestimmte
Elementfunktion aus der Bibliothek an die Client-Anwendung
zurückgibt, als Antwort auf den Satzdatensatz und gültige
Verknüpfungszeiger in den Funktionsverknüpfungscachespeicher und den
Satzverknüpfungscachespeicher schreibt.
20. Vorrichtung nach Anspruch 19, mit mehreren
Verknüpfungsstrukturen im internen Speicher und wobei den
Funktionssätzen laufende Nummern zugeordnet werden, wenn sie in den
internen Speicher geladen werden;
der Satzverknüpfungscachespeicher einen Zeiger zu einer
der mehreren Verknüpfungsstrukturen und eine laufende Nummer
speichert, die eine laufende Nummer des entsprechenden
Funktionssatzes anzeigt, wenn der Satzverknüpfungscachespeicher
gefüllt ist;
die Verknüpfungsstruktur einen Zeiger zum Satzdatensatz
aufweist; und
die Verknüpfungsmaschine eine Routine aufweist, um den
Verknüpfungszeiger und die laufende Nummer an den
Satzverknüpfungscachespeicher zu liefern, als Antwort auf die Rückgabe
der bestimmten Elementfunktion an den Client;
die Zuteilmaschine eine Routine aufweist, die die
Gültigkeit eines cachegespeicherten Verknüpfungszeigers zu dem
Satzdatensatz sicherstellt, als Antwort auf die laufende
Nummer im Satzverknüpfungscachespeicher und die laufende Nummer
im Satzdatensatz.
Applications Claiming Priority (2)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
US08/085,187 US5615400A (en) | 1993-06-30 | 1993-06-30 | System for object oriented dynamic linking based upon a catalog of registered function set or class identifiers |
PCT/US1994/007424 WO1995001598A1 (en) | 1993-06-30 | 1994-06-30 | System for object oriented dynamic linking based upon a catalog of registered function set or class identifiers |
Publications (2)
Publication Number | Publication Date |
---|---|
DE69414387D1 DE69414387D1 (de) | 1998-12-10 |
DE69414387T2 true DE69414387T2 (de) | 1999-07-15 |
Family
ID=22190014
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
DE69414387T Expired - Lifetime DE69414387T2 (de) | 1993-06-30 | 1994-06-30 | Objektorientiertes dynamisches "link"-system, welches auf katalogisierte funktionen und klassen zugreift |
Country Status (6)
Country | Link |
---|---|
US (1) | US5615400A (de) |
EP (1) | EP0706684B1 (de) |
AU (1) | AU7253894A (de) |
CA (1) | CA2166302C (de) |
DE (1) | DE69414387T2 (de) |
WO (1) | WO1995001598A1 (de) |
Families Citing this family (105)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US5379432A (en) * | 1993-07-19 | 1995-01-03 | Taligent, Inc. | Object-oriented interface for a procedural operating system |
FR2717280B1 (fr) * | 1994-03-10 | 1996-04-05 | Bull Sa | Procédé de gestion de l'héritage multiple d'objets persistants et partagés. |
US5831606A (en) * | 1994-12-13 | 1998-11-03 | Microsoft Corporation | Shell extensions for an operating system |
US5956715A (en) | 1994-12-13 | 1999-09-21 | Microsoft Corporation | Method and system for controlling user access to a resource in a networked computing environment |
CA2143488C (en) * | 1995-02-27 | 2000-01-11 | Robert Paul Duncan | Dynamic link libraries without linker or loader support |
US6519767B1 (en) * | 1995-06-07 | 2003-02-11 | Microsoft Corporation | Compiler and method for automatically building version compatible object applications |
US5764991A (en) * | 1995-06-30 | 1998-06-09 | Canon Kabushiki Kaisha | Processing object oriented code and virtual function code |
JPH09231156A (ja) * | 1996-02-28 | 1997-09-05 | Nec Corp | プログラム受信機能付遠隔実行装置 |
US5805796A (en) * | 1996-03-27 | 1998-09-08 | Dell Usa, Lp | System architecture for implementing modular diagnostics |
US6704802B1 (en) * | 1996-03-27 | 2004-03-09 | Dell Usa, Lp | Method and system for communicating between independent software modules |
US6052778A (en) * | 1997-01-13 | 2000-04-18 | International Business Machines Corporation | Embedded system having dynamically linked dynamic loader and method for linking dynamic loader shared libraries and application programs |
US5930795A (en) * | 1997-01-21 | 1999-07-27 | International Business Machines Corporation | Supporting dynamic tables in SQL query compilers |
US6363436B1 (en) | 1997-01-27 | 2002-03-26 | International Business Machines Corporation | Method and system for loading libraries into embedded systems |
US6055562A (en) * | 1997-05-01 | 2000-04-25 | International Business Machines Corporation | Dynamic mobile agents |
US6442753B1 (en) * | 1997-08-28 | 2002-08-27 | International Business Machines Corporation | Apparatus and method for checking dependencies among classes in an object-oriented program |
US6078889A (en) * | 1997-09-30 | 2000-06-20 | Pitney Bowes Inc. | Method and system of implementing a carrier manager librarian |
US6873978B1 (en) | 1997-10-01 | 2005-03-29 | Pitney Bowes Inc. | Event interface for a carrier manager system |
US6910047B1 (en) | 1997-10-01 | 2005-06-21 | Pitney Bowes Inc. | Method and system for changing rating data via internet or modem in a carrier management system |
US6292843B1 (en) | 1998-01-16 | 2001-09-18 | International Business Machines Corporation | Quick loading of run time dynamic link library for OS/2 |
JP3284956B2 (ja) * | 1998-01-26 | 2002-05-27 | 日本電気株式会社 | プログラム変換方法、プログラム変換装置及びプログラム変換プログラムを記憶した記憶媒体 |
DE19810675A1 (de) * | 1998-03-12 | 1999-10-14 | Giesecke & Devrient Gmbh | Datenträger |
US6061520A (en) * | 1998-04-07 | 2000-05-09 | Sun Microsystems, Inc. | Method and system for performing static initialization |
US6182277B1 (en) * | 1998-04-15 | 2001-01-30 | Oracle Corporation | Methods and apparatus for declarative programming techniques in an object oriented environment |
US6079015A (en) * | 1998-04-20 | 2000-06-20 | Motorola, Inc. | Data processing system having selectable exception table relocation and method therefor |
AUPP365798A0 (en) * | 1998-05-22 | 1998-06-18 | Ladd, James Christian | Architecture for the execution of program code |
US6314566B1 (en) * | 1998-09-29 | 2001-11-06 | Apple Computer, Inc. | Method and apparatus for “Just-in-Time” dynamic loading and unloading of computer software libraries |
JP3837244B2 (ja) | 1998-10-23 | 2006-10-25 | 松下電器産業株式会社 | プログラムリンク装置及び方法 |
US6343294B1 (en) * | 1998-12-15 | 2002-01-29 | International Business Machines Corporation | Data file editor for multiple data subsets |
US6286010B1 (en) * | 1999-02-19 | 2001-09-04 | Novell, Inc. | Methods and apparatuses for interaction between schemata |
US6393491B1 (en) | 1999-04-26 | 2002-05-21 | Sun Microsystems, Inc. | Method and apparatus for dispatch table construction |
US7171673B1 (en) * | 1999-08-06 | 2007-01-30 | Honeywell International Inc. | System and method for validating interfaces of dynamically linkable components and real-time process control system incorporating the same |
US6457170B1 (en) * | 1999-08-13 | 2002-09-24 | Intrinsity, Inc. | Software system build method and apparatus that supports multiple users in a software development environment |
GB9921720D0 (en) * | 1999-09-14 | 1999-11-17 | Tao Group Ltd | Loading object-oriented computer programs |
US7080370B1 (en) * | 1999-11-05 | 2006-07-18 | Sun Microsystems, Inc. | Method and apparatus for compiling source programs using one or more libraries |
US6385722B1 (en) | 2000-01-27 | 2002-05-07 | Sun Microsystems, Inc. | Method, system, and article of manufacture for limiting access to program files in a shared library file |
US7343421B1 (en) * | 2000-02-14 | 2008-03-11 | Digital Asset Enterprises Llc | Restricting communication of selected processes to a set of specific network addresses |
US7089242B1 (en) * | 2000-02-29 | 2006-08-08 | International Business Machines Corporation | Method, system, program, and data structure for controlling access to sensitive functions |
US6658657B1 (en) * | 2000-03-31 | 2003-12-02 | Intel Corporation | Method and apparatus for reducing the overhead of virtual method invocations |
US6907421B1 (en) | 2000-05-16 | 2005-06-14 | Ensim Corporation | Regulating file access rates according to file type |
US7143024B1 (en) * | 2000-07-07 | 2006-11-28 | Ensim Corporation | Associating identifiers with virtual processes |
US6505123B1 (en) * | 2000-07-24 | 2003-01-07 | Weatherbank, Inc. | Interactive weather advisory system |
US6877162B1 (en) * | 2000-07-31 | 2005-04-05 | Hewlett-Packard Company | Method and system for extendable class-based shared data-types |
US6625703B2 (en) | 2000-11-02 | 2003-09-23 | International Business Machines Corporation | Verifying primary and backup copies of vital information for a processing system employing a pseudo-fixed reference identifier |
US7219354B1 (en) | 2000-12-22 | 2007-05-15 | Ensim Corporation | Virtualizing super-user privileges for multiple virtual processes |
JP2002373077A (ja) * | 2001-06-14 | 2002-12-26 | Nec Corp | 実行時ライブラリ検索方法及び装置、動的リンカ並びにプログラム |
US6986148B2 (en) * | 2001-07-17 | 2006-01-10 | Appforge, Inc. | Methods and systems for providing platform-independent shared software components for mobile devices |
US6934943B2 (en) * | 2001-10-18 | 2005-08-23 | Hewlett-Packard Development Company | Optimization of control transfers to dynamically loaded modules |
US7007273B2 (en) * | 2001-10-29 | 2006-02-28 | Lenovo (Singapore) Pte Ltd. | Object oriented model of preloading software |
US6981268B2 (en) * | 2001-12-05 | 2005-12-27 | Microsoft Corporation | System and method for persisting and resolving application assembly binds |
US20030182361A1 (en) * | 2002-03-22 | 2003-09-25 | Sun Microsystems, Inc. | Business-model agnostic service deployment management service |
US7644411B1 (en) * | 2002-06-06 | 2010-01-05 | Unisys Corporation | Mechanism for implementing different types of services within the same two-phase commit transaction |
CN100407728C (zh) * | 2002-08-02 | 2008-07-30 | 中兴通讯股份有限公司 | 一种分布式系统对象之间的板间通信方法 |
US7451458B2 (en) * | 2002-08-02 | 2008-11-11 | Tuchow Jonathan A | Software methods of an optical networking apparatus with multiple multi-protocol optical networking modules having packet filtering resources |
US7844734B2 (en) * | 2002-11-18 | 2010-11-30 | Innopath Software, Inc. | Dynamic addressing (DA) using a centralized DA manager |
US20050091259A1 (en) * | 2003-10-24 | 2005-04-28 | Microsoft Corporation Redmond Wa. | Framework to build, deploy, service, and manage customizable and configurable re-usable applications |
US7155726B2 (en) * | 2003-10-29 | 2006-12-26 | Qualcomm Inc. | System for dynamic registration of privileged mode hooks in a device |
US7164972B2 (en) * | 2004-06-28 | 2007-01-16 | Siemens Building Technologies, Inc. | Method and apparatus for representing a building system |
US7552302B1 (en) * | 2004-09-14 | 2009-06-23 | Azul Systems, Inc. | Ordering operation |
US8037482B1 (en) * | 2004-09-14 | 2011-10-11 | Azul Systems, Inc. | Accelerated class check |
US20060161469A1 (en) | 2005-01-14 | 2006-07-20 | Weatherbank, Inc. | Interactive advisory system |
US8832121B2 (en) * | 2005-02-02 | 2014-09-09 | Accuweather, Inc. | Location-based data communications system and method |
US7644416B2 (en) * | 2005-02-10 | 2010-01-05 | Google Inc. | Access to a target object with desired functionality |
US7743379B2 (en) * | 2005-07-14 | 2010-06-22 | International Business Machines Corporation | Variable resource sets |
US20070169026A1 (en) * | 2005-11-28 | 2007-07-19 | Davis Alan H | Software program with alternative function libraries |
US8229467B2 (en) | 2006-01-19 | 2012-07-24 | Locator IP, L.P. | Interactive advisory system |
US8291395B2 (en) * | 2006-03-31 | 2012-10-16 | Apple Inc. | Fast function call dispatching |
US8549544B1 (en) * | 2006-04-07 | 2013-10-01 | Intel Corporation | System, method and computer program product for preventing the execution of unwanted code |
GB0609843D0 (en) * | 2006-05-18 | 2006-06-28 | Ibm | Launcher for software applications |
US8634814B2 (en) | 2007-02-23 | 2014-01-21 | Locator IP, L.P. | Interactive advisory system for prioritizing content |
US20080222611A1 (en) * | 2007-03-09 | 2008-09-11 | Microsoft Corporation | Generic validation layer for object properties |
US8539480B2 (en) * | 2007-04-09 | 2013-09-17 | Sugarcrm Inc. | Multi-instance “shadow” system and method for automated resource redundancy reduction across dynamic language applications utilizing application of dynamically generated templates |
GB0712654D0 (en) * | 2007-06-28 | 2007-08-08 | Symbian Software Ltd | Computing device having an embedded rom image |
US20090259999A1 (en) * | 2008-04-11 | 2009-10-15 | Oracle International Corporation | Method and system for applying a patch during application execution |
US8327323B2 (en) * | 2008-12-08 | 2012-12-04 | International Business Machines Corporation | Automatic copying by ancestor in object-oriented languages |
US8190587B1 (en) * | 2008-12-11 | 2012-05-29 | Network Appliance, Inc. | In-place image promotion |
KR100892882B1 (ko) * | 2008-12-24 | 2009-04-15 | 고혜선 | 물품관리방법 |
US9811353B1 (en) * | 2010-07-29 | 2017-11-07 | Crimson Corporation | Remotely invoking dynamic classes on a computing device |
JP5682220B2 (ja) * | 2010-10-14 | 2015-03-11 | 株式会社リコー | 情報処理装置、情報処理方法、及び情報処理プログラム |
US8321480B2 (en) * | 2010-11-24 | 2012-11-27 | Bmc Software, Inc. | Full-function to high availability large database conversion |
US9665601B1 (en) | 2010-12-16 | 2017-05-30 | Crimson Corporation | Using a member attribute to perform a database operation on a computing device |
US8438532B2 (en) | 2011-04-19 | 2013-05-07 | Sonatype, Inc. | Method and system for scoring a software artifact for a user |
US8612936B2 (en) | 2011-06-02 | 2013-12-17 | Sonatype, Inc. | System and method for recommending software artifacts |
US9015661B1 (en) * | 2011-06-23 | 2015-04-21 | The Mathworks, Inc. | Restricting class inheritance relationships |
US8473894B2 (en) | 2011-09-13 | 2013-06-25 | Sonatype, Inc. | Method and system for monitoring metadata related to software artifacts |
US8627270B2 (en) | 2011-09-13 | 2014-01-07 | Sonatype, Inc. | Method and system for monitoring a software artifact |
US9141378B2 (en) | 2011-09-15 | 2015-09-22 | Sonatype, Inc. | Method and system for evaluating a software artifact based on issue tracking and source control information |
US8656343B2 (en) | 2012-02-09 | 2014-02-18 | Sonatype, Inc. | System and method of providing real-time updates related to in-use artifacts in a software development environment |
US8825689B2 (en) | 2012-05-21 | 2014-09-02 | Sonatype, Inc. | Method and system for matching unknown software component to known software component |
US9141408B2 (en) * | 2012-07-20 | 2015-09-22 | Sonatype, Inc. | Method and system for correcting portion of software application |
US8984542B2 (en) * | 2012-11-30 | 2015-03-17 | Facebook, Inc. | Method and system for binding objects in dynamic programming languages using caching techniques |
US9135263B2 (en) | 2013-01-18 | 2015-09-15 | Sonatype, Inc. | Method and system that routes requests for electronic files |
US9830135B2 (en) | 2014-01-29 | 2017-11-28 | Dell Products L.P. | Declarative and pluggable business logic for systems management |
US10656971B2 (en) | 2014-01-31 | 2020-05-19 | Dell Products L.P. | Agile framework for vertical application development and delivery |
US9626251B2 (en) | 2014-01-31 | 2017-04-18 | Dell Products L.P. | Undo configuration transactional compensation |
US10114861B2 (en) | 2014-01-31 | 2018-10-30 | Dell Products L.P. | Expandable ad hoc domain specific query for system management |
US9459859B2 (en) | 2014-01-31 | 2016-10-04 | Dell Products L.P. | Template derivation for configuration object management |
JP6409514B2 (ja) * | 2014-11-10 | 2018-10-24 | 日本電気株式会社 | 情報処理装置およびライブラリロード方法、並びにコンピュータ・プログラム |
US9519468B2 (en) * | 2015-02-13 | 2016-12-13 | Oracle International Corporation | Modular co-versioning in a dynamically linked runtime environment |
US9971594B2 (en) | 2016-08-16 | 2018-05-15 | Sonatype, Inc. | Method and system for authoritative name analysis of true origin of a file |
US11113180B2 (en) * | 2020-01-31 | 2021-09-07 | Salesforce.Com, Inc. | Efficiently tracking code location of run-time events in system software |
CN113625995A (zh) * | 2020-05-07 | 2021-11-09 | 武汉斗鱼网络科技有限公司 | 一种自适应获取数据的方法和装置 |
US11347523B2 (en) | 2020-11-05 | 2022-05-31 | International Business Machines Corporation | Updated shared library reloading without stopping the execution of an application |
US11681520B2 (en) * | 2021-04-20 | 2023-06-20 | International Business Machines Corporation | Software upgrading using dynamic link library injection |
US11675593B2 (en) | 2021-08-31 | 2023-06-13 | International Business Machines Corporation | Dynamically updating a dynamic library |
CN115794260B (zh) * | 2023-02-06 | 2023-05-05 | 湖南高至科技有限公司 | 一种简单的dsp软件库动态加载方法 |
Family Cites Families (18)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
GB2203572B (en) * | 1987-03-24 | 1991-11-27 | Insignia Solutions Limited | Improvements in data processing means |
WO1988007718A1 (en) * | 1987-03-24 | 1988-10-06 | Insignia Solutions Limited | Arrangement for software emulation |
US5261080A (en) * | 1987-08-21 | 1993-11-09 | Wang Laboratories, Inc. | Matchmaker for assisting and executing the providing and conversion of data between objects in a data processing system storing data in typed objects having different data formats |
JP2569092B2 (ja) * | 1987-12-11 | 1997-01-08 | 株式会社日立製作所 | 入出力機器制御プログラムのアドレス解決方法 |
US5269021A (en) * | 1989-10-12 | 1993-12-07 | Texas Instruments Incorporated | Multiprocessor software interface for a graphics processor subsystem employing partially linked dynamic load modules which are downloaded and fully linked at run time |
US5247678A (en) * | 1989-10-12 | 1993-09-21 | Texas Instruments Incorporated | Load time linker for software used with a multiprocessor system |
GB2242293A (en) * | 1990-01-05 | 1991-09-25 | Apple Computer | Apparatus and method for dynamic linking of computer software components |
US5297279A (en) * | 1990-05-30 | 1994-03-22 | Texas Instruments Incorporated | System and method for database management supporting object-oriented programming |
US5317703A (en) * | 1990-06-29 | 1994-05-31 | Hitachi, Ltd. | Information processing apparatus using an advanced pipeline control method |
US5204947A (en) * | 1990-10-31 | 1993-04-20 | International Business Machines Corporation | Application independent (open) hypermedia enablement services |
US5297249A (en) * | 1990-10-31 | 1994-03-22 | International Business Machines Corporation | Hypermedia link marker abstract and search services |
US5247681A (en) * | 1990-12-18 | 1993-09-21 | International Business Machines Corporation | Dynamic link libraries system and method |
US5421016A (en) * | 1991-12-12 | 1995-05-30 | International Business Machines Corporation | System and method for dynamically invoking object methods from an application designed for static method invocation |
EP0546682A3 (en) * | 1991-12-12 | 1993-12-08 | Ibm | Parent class shadowing |
US5359721A (en) * | 1991-12-18 | 1994-10-25 | Sun Microsystems, Inc. | Non-supervisor mode cross address space dynamic linking |
US5339430A (en) * | 1992-07-01 | 1994-08-16 | Telefonaktiebolaget L M Ericsson | System for dynamic run-time binding of software modules in a computer system |
US5375241A (en) * | 1992-12-21 | 1994-12-20 | Microsoft Corporation | Method and system for dynamic-link library |
US5315703A (en) * | 1992-12-23 | 1994-05-24 | Taligent, Inc. | Object-oriented notification framework system |
-
1993
- 1993-06-30 US US08/085,187 patent/US5615400A/en not_active Expired - Lifetime
-
1994
- 1994-06-30 WO PCT/US1994/007424 patent/WO1995001598A1/en active IP Right Grant
- 1994-06-30 CA CA002166302A patent/CA2166302C/en not_active Expired - Lifetime
- 1994-06-30 AU AU72538/94A patent/AU7253894A/en not_active Abandoned
- 1994-06-30 EP EP94922068A patent/EP0706684B1/de not_active Expired - Lifetime
- 1994-06-30 DE DE69414387T patent/DE69414387T2/de not_active Expired - Lifetime
Also Published As
Publication number | Publication date |
---|---|
US5615400A (en) | 1997-03-25 |
EP0706684A1 (de) | 1996-04-17 |
CA2166302C (en) | 2004-12-07 |
DE69414387D1 (de) | 1998-12-10 |
CA2166302A1 (en) | 1995-01-12 |
WO1995001598A1 (en) | 1995-01-12 |
EP0706684B1 (de) | 1998-11-04 |
AU7253894A (en) | 1995-01-24 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
DE69414387T2 (de) | Objektorientiertes dynamisches "link"-system, welches auf katalogisierte funktionen und klassen zugreift | |
DE69230578T2 (de) | Sprachenneutrale Objekte | |
DE69627926T2 (de) | Verfahren und Gerät zum Erzeugen und Installieren von verteilten Objekten auf einem verteilten Objektsystem | |
DE69621381T2 (de) | Verfahren und Vorrichtung zur internen Versionsbildung von Objekten unter Verwendung einer Datei | |
DE69400871T2 (de) | Objektorientiertes betriebssystem | |
DE69617509T2 (de) | Vorrichtung und Verfahren zur Feststellung von Objekttypen in einem verteilten Objektsystem | |
DE69800686T2 (de) | Verfahren und Gerät für effizienten Operationen auf primären Typwerten ohne statisches Überladen | |
DE69800909T2 (de) | Verfahren und Vorrichtung zur Optimierung der präzisen Speicherbereinigung, bei der Programmschleifen mit Zeiger-Feldern verwendet werden | |
DE69321255T2 (de) | Vorrichtung zur ausführung vom mehreren programmteilen mit verschiedenen objektcodetypen in einem einzigen programm oder in einer prozessorumgebung | |
DE69615637T2 (de) | Verfahren zur objektorientierten Programmierung mit dynamischer Schnittstelle | |
Sakkinen | Disciplined Inheritance. | |
DE69402852T2 (de) | Objektorientiertes host-system | |
US6202208B1 (en) | Patching environment for modifying a Java virtual machine and method | |
DE60031370T2 (de) | Tokenbasierte verknüpfung | |
DE102010051477B4 (de) | Verfahren in einer computerplattform sowie computerplattform zum gemeinsamen benutzen von virtuellen speicherbasierten mehrversionsdaten zwischen den verschiedenartigen prozessoren der computerplattform | |
Johnson et al. | Refactoring and aggregation | |
US5752034A (en) | Apparatus and method for providing an event detection notification service via an in-line wrapper sentry for a programming language | |
DE69503065T2 (de) | Objektorientierte vorrichtung für konfigurationsverlaufsverwaltung | |
DE69327243T2 (de) | System und verfahren zur dynamischen laufzeit-bindung von software-modulen in einem rechnersystem. | |
DE69625636T2 (de) | System und Verfahren zum Steuern und Verwalten von verteilten Objektservern unter Verwendung von erstklassigen verteilten Objekten | |
DE69131530T2 (de) | Datenbankverwaltungssystem und -verfahren zur Unterstützung von objektorientierter Programmierung | |
DE60006410T2 (de) | Verfahren und system zum verteilen von objektorientierten rechnerprogrammen | |
DE68921775T2 (de) | Prozessorssimulation. | |
DE69938218T2 (de) | Vorrichtung und Verfahren zum Laden eines Java Anwendungsprogramms | |
DE69518446T2 (de) | Typsicheres Rahmenwerk für dynamisch erweiterbare Objekte |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
8364 | No opposition during term of opposition | ||
8327 | Change in the person/name/address of the patent owner |
Owner name: APPLE INC., CUPERTINO, CALIF., US |