Großer Beleg. API für Plugin und Treiber basierte Softwareentwicklung

Größe: px
Ab Seite anzeigen:

Download "Großer Beleg. API für Plugin und Treiber basierte Softwareentwicklung"

Transkript

1 TECHNISCHE UNIVERSITÄT DRESDEN FAKULTÄT INFORMATIK INSTITUT FÜR SOFTWARE- UND MULTIMEDIATECHNIK PROFESSUR FÜR COMPUTERGRAPHIK UND VISUALISIERUNG PROF. DR. STEFAN GUMHOLD Großer Beleg API für Plugin und Treiber basierte Softwareentwicklung Michael Voß (Mat.-Nr.: ) Betreuer: Prof. Dr. rer. nat. Stefan Gumhold Dresden, 27. April 2007

2 Aufgabenstellung Entwicklung von plattformunabhängigen Konzepten für die Realisierung von Plugins und Treiber in computergraphischen Anwendungen.

3 1 Inhaltsverzeichnis 1 Einführung 3 2 Grundlagen Hostanwendung, Plugins und Schnittstellen Programmiersprache Native Sprachen NET Framework und Mono Interoperabilität Bibliotheken Statische Bibliotheken Dynamische Bibliotheken Windows und dynamische Bibliotheken Linux und dynamische Bibliotheken Beispiele für Pluginsysteme Adobe Photoshop Plugins Qt Plugins Die Plugin API für C Typenreflektion mit dynamic_cast Schnittstellendefinitionen in PluginDefs Plugin_interface_class Iplugin_base Irenderable Id3d9_plugin IPluginEventCallback Ikeyboard_event_handler Imouse_event_handler Die Verwaltungsklasse plugin_loader

4 Laden neuer Plugins Pluginliste Zugriff auf Plugins Plugin Bibliotheken schreiben plugin_factory_list_class Pluginfabriken Die Plugin API für.net Typenreflektion im.net Framework Schnittstellen in PluginDefs Die Standardschnittstelle iplugin_base Iplugin_event_callback PluginLoader.NET Beispielanwendungen DirectX Beispiel für C Die Hostanwendung Die Dll MeshDll Die DLL InteractiveRoom OpenGL Beispiel für C OpenGLHost Die Pluginbibliothek OGLDLL Beispiel für.net Hostanwendung Das Assembly PluginDLL Zusammenfassung 37 Literaturverzeichnis 38 Abbildungsverzeichnis 40 A Quelltexte 41 B Verzeichnisse auf der CD zum Beleg 46

5 1. EINFÜHRUNG 3 1 Einführung Arbeitet man an einem kommerziellen Software-Projekt, muss man sich irgendwann entscheiden, welche Funktionen implementiert werden sollen. Diese Entscheidung wird im Normalfall mit Hilfe des Verhältnisses zwischen Nutzen und Kosten getroffen. Spezielle Wünsche werden selten berücksichtigt, weil sie für den durchschnittlichen Kunden kaum eine Verbesserung bringen. Oft ändern sich aber die Anforderungen an die Software im Verlauf des Nutzungszeitraums und je nach Anwender. Aus diesem Grund ist es vorteilhaft, wenn der Software ohne erneutes Kompilieren Funktionen hinzugefügt werden können. Weiterhin gibt es einige Anwendungsbereiche, wo es von Vorteil ist, wenn viele kleine Projekte in einer gemeinsamen Oberfläche zusammengefasst werden können. Dabei sollte die grafischen Benutzerschnittstellen nicht für jedes Projekt einzeln gestaltet werden, sondern einheitlich und zentral. Manchmal ist es nötig, dass eine Anwendung je nach Bedarf ihre grafischen Ausgaben mit Hilfe von DirectX, OpenGL oder den Betriebssystemfunktionen realisiert. Hier wäre es schön, wenn die Anwendung nicht für alle Systeme komplett neu geschrieben werden müsste und wenn die Wahl des System so dynamisch wie möglich ist. Dies alles kann durch Pluginsysteme realisiert werden. Solche Systeme sind in der Lage Programmteile, welche Plugins genannt werden, einer Anwendung dynamisch hinzuzufügen. Das Wort Plugin kommt vom englischen to plug in und bedeutet soviel wie einstöpseln oder anschließen. Das Erweitern von Anwendungen durch Plugins wird im Rahmen vorher definierter Grenzen, den Schnittstellen, durchgeführt. Schnittstellen sind eine Art Regelung der Kommunikation zwischen Anwendung und hinzugefügten Programmteil. So wird es möglich, Erweiterungen für Applikationen zu schreiben, von denen die Schnittstellen bekannt sind, auch wenn der Quellcode unbekannt bleibt. Viele moderne Anwendungen für Desktoprechner unterstützen die Erweiterung mittels Plugins. So können spezielle Inhalte wie Animationen, PDF Dateien und Videos über den Internetbrowser Firefox [15] betrachtet werden. Für das 3d Modellierungs- und Animationsprogramm 3d Studio MAX [4] sind z. B. physikalische Systeme, Stoffsimulationen und verschiedene Partikeleffekte als Erweiterungen im Internet zu finden. Ein weiteres Beispiel ist Adobe Photoshop [1]. Für diese Bildbearbeitungssoftware gibt es zahlreiche Plugins. Sie werden Filter genannt und verändern das aktuell ausgewählte Bild in spezifischer Weise. In diesem Beleg geht es darum, eine Programmierschnittstelle (API) zu entwickeln, mit deren Hilfe ei-

6 1. EINFÜHRUNG 4 ne pluginbasierte Anwendung schnell und einfach geschrieben werden kann. Diese API soll sowohl in einem Windows Betriebssystem, als auch unter Linux kompilierbar sein. Die API soll zudem flexibel und erweiterbar sein. Weiterhin soll Untersucht werden ob eine einheitliche API für C++ - und.net Anwendungen möglich ist. Der Anwendungsfall an dem sich bei der Entwicklung der Plugin API orientiert wurde, ist eine grafische Applikation die als Benutzerschnittstelle fungiert und Plugins, die bis auf die Interaktion mit dem Benutzer, komplett selbständige Programme darstellen. Die API wurde in den Namensraum cgv::utils::plugins geschrieben und hält sich an die vorgegebene Namenskonvention.

7 2. GRUNDLAGEN 5 2 Grundlagen 2.1 Hostanwendung, Plugins und Schnittstellen Jedes Pluginsystem besteht im wesentlichen aus zwei Komponenten. Zum Einen aus der Hostanwendung, welche als solche vom Anwender gestartet wird und den Rahmen der Funktionalität bestimmt. Zum Anderen aus den Plugins, welche von der Hostanwendung geladen werden und dieser neue Funktionen hinzufügen können. Plugins werden typischer Weise in dynamische Bibliotheken verpackt. Zur Kommunikation zwischen Hostanwendung und Plugin werden Schnittstellen definiert. Diese Schnittstellen müssen für beide Seiten gleich sein und vor dem Kompilieren der Hostanwendung angegeben werden. Aus diesem Grund dürfen einmal definierte Schnittstellen in der hier vorgestellten API nicht mehr geändert werden, da sonst neue Plugins nicht mehr mit alten Anwendungen kompatibel wären bzw. alte Plugins mit neuen Anwendungen. Sie können aber zur Erweiterung der API als Basisklassen genutzt werden, wenn sie für eine neue Schnittstelle notwendig sind. 2.2 Programmiersprache Im Bereich der Programmiersprachen ist mit Einführung von.net [13], und dessen Portierung auf Linux: Mono [14], eine Einteilung in managed und native oder auch unmanaged entstanden. Bei dieser Unterteilung werden alle Sprachen und Programme die das.net Framework nutzen als managed bezeichnet. Alle übrig bleibenden Sprachen werden native oder unmanaged genannt. Die im Rahmen dieses Beleges erstellte API ist dieser Aufteilung folgend auch zweigeteilt Native Sprachen Der native Teil der Plugin API besteht aus drei statischen Bibliotheken und einigen C++ Headern und ist für den Gebrauch mit C++ gedacht. Die Bibliotheken enthalten Schnittstellen für Plugins, eine Verwaltungsklasse zur Nutzung von Plugins in Anwendungen und eine Verwaltungsklasse für alle in einer Pluginbibliothek enthaltenen Plugins.

8 2. GRUNDLAGEN NET Framework und Mono Abbildung 2.1: CTS Typenhierarchie ([7]) Das.NET Framework wurde von Microsoft als Konkurrenz zu Java entwickelt und sollte den Anforderungen von verteilten Anwendungen genügen. Es besteht im wesentlichen aus einer virtuellen Maschine, welche Common Language Runtime (CLR) genannt wird und dem Framework selbst. Die Implementierung orientiert sich an der CLI (Common Language Infrastructure), einem Standard, der Systeme spezifiziert, die sprach- und plattformneutrale Anwendungsentwicklung und -ausführung ermöglichen. Wie bei Java wird beim Kompilieren zunächst eine Art Zwischencode (CIL für Common Intermediate Language) erzeugt. Ein in CIL kompiliertes Programm bzw. Programmteil wird als Assembly bezeichnet. Assemblies können sowohl selbständig ausführbare Dateien (in Windows EXE-Dateien) als auch Bibliotheken sein. Sie enthalten neben dem Code in CIL zusätzlich Metadaten, welche das Assembly und darin enthaltene Definitionen näher beschreiben. Zum Ausführen eines Assemblies durch die virtuelle Maschine, im Falle von.net der CLR, wird der Zwischencode in nativen Maschinencode umgewandelt. Diese Art der Kompilierung in Maschinencode direkt vor dem Ausführen wird just-in-time (JIT) Kompilierung genannt. Da dies negativ auf die Startzeit eines Assemblies wirkt, kann für zeitkritische

9 2. GRUNDLAGEN 7 Anwendungen, also Anwendungen die schnell gestartet werden sollen, bereits vor der Ausführung durch die CLR, nativer Maschinencode erzeugt werden. Dieses Verfahren nennt sich NGen (Native Image Generation) und wird typischer Weise bei der Installation der Anwendung ausgeführt. Es wird also wie beim JIT kompilieren ein auf das System angepasster und optimierter nativer Maschinencode erzeugt, der nicht für die Weitergabe und Ausführung auf anderen Systemen gedacht ist. Assemblies werden in CIL dem Binärformat der CLR weitergegeben. Ein weiterer Bestandteil der CLI ist ein wohldefiniertes Typensystem. Das Common Type System (CTS) stellt ein einheitliches System von Datentypen bereit. Abbildung 2.1 zeigt die Typenhierarchie des CTS.[7] Im Gegensatz zu Java, ist das.net Framework an keine Programmiersprache gebunden. Neben C#, welches extra für die effiziente Nutzung des Frameworks entworfen wurde, gibt es eine Vielzahl von.net fähigen Programmiersprachen. Einige wie C++ mit Managed Extensions (C++/CLI) oder Delphi.NET können sowohl managed.net Code als auch unmanaged Code kompilieren. Da bei jedem.net Kompiler ein Zwischencode (CIL) erzeugt wird, ist die Wahl der Sprache keine Einschränkung bezüglich der Kompatibilität. So können.net Sprachen alle Komponenten und Bibliotheken nutzen die von einer beliebigen anderen.net Sprache erzeugt wurden. Das.NET Framework ist zur Zeit nur für die Windows Betriebssysteme ab Windows 98 erhältlich. Um auch unter Linux Assemblies erzeugen zu können, muss man auf Open-Source Projekte wie Mono zurückgreifen. Das Mono-Projekt[14] orientiert sich ebenfalls an der CLI und beinhaltet eine eigene virtuelle Maschine, eine zum.net Framework kompatible Sammlung von Klassenbibliotheken sowie einen Kompiler für die Sprache C#. Mono gibt es neben Linux auch für Mac OS X, Sun Solaris, BSD und Windows. Dadurch ist es möglich, Anwendungen für das.net Framework auch unter anderen Betriebssystemen als Windows auszuführen. Der managed Teil der Plugin API besteht aus zwei Assemblies. Diese Klassenbibliotheken stellen eine Verwaltungsklasse und Schnittstellen für Plugins bereit Interoperabilität Bei der Entwicklung vom.net Framework wurde auch auf die Zusammenarbeit mit unmanaged Code geachtet. Allerdings bezieht sich diese Zusammenarbeit vor allem auf COM Projekte. COM steht für component object model und bezeichnet eine Technologie, welche eine von der Programmiersprache unabhängige Möglichkeit der Objektbeschreibung und Objekterzeugung bietet (für weitere Informationen siehe [16]). Diese von Microsoft entwickelte Technologie findet aber nur in Windows Betriebssystemen Verwendung. Für eine plattformunabhängige API ist COM also ungeeignet. Im.NET Framework existiert neben der Unterstützung von COM noch eine weitere Variante der Inter-

10 2. GRUNDLAGEN 8 operabilität. Diese nennt sich Platform Invoke Service oder auch PInvoke Service. PInvoke unterstützt Aufrufe von exportierten globalen Methoden und nicht statischen Memberfunktionen einer unmanaged DLL. Dies geschieht über das DllImport Attribut. Die dabei notwendige Konvertierung der nativen Typen in managed Typen und umgekehrt wird Marshaling genannt (siehe [18]). Leider gibt es keine Möglichkeit, eine Instanz einer Klasse (Objekte) zu konvertieren. Es müssten also Wrapperklassen geschrieben werden, welche für jede Methode des zu konvertierenden Objektes, eigene Funktionszeiger besitzt. Diese Herangehensweise ist aber für eine flexible Plugin API, wie die hier vorgestellte, sehr hinderlich. Es müsste jeweils in C++ und.net die Schnittstelle und eine zugehörige Wrapperklasse definiert werden. Dies bedeutet gegenüber der Aufteilung der API in einen.net und einen C++ Teil, zwei zusätzliche Klassen. Es wurde aus diesem Grund von einer einheitlichen API abgesehen und die angesprochene Teilung vollzogen. Ist eine Zusammenarbeit von.net Hostanwendung und unmanaged Plugin (oder auch umgekehrt) unbedingt nötig, dann kann auf die Managed Extensions von C++ zurückgegriffen werden. Die Hostanwendung besteht dann aus einem managed und einem unmanaged Teil und es ist dem Entwickler der Hostanwendung überlassen, sich um die Kommunikation zwischen.net und C++ zu kümmern. Dies bedeutet im Normalfall deutlich weniger Aufwand, weil die Hostanwendung die Art der genutzten Plugins kennt. Sie muss unter diesem Gesichtspunkt also weniger flexibel sein. 2.3 Bibliotheken Eine Bibliothek bezeichnet in der Programmierung eine kompilierte Sammlung von Funktionen, Variablen und Konstanten, welche von Programmen genutzt werden können. Häufig verwendete Programmteile werden auf allen gängigen Betriebssystemen in solche Bibliotheken ausgelagert. Sie müssen dann bei der Programmierung einer Anwendung nicht erneut geschrieben werden, sondern es werden die benötigten Teile aus der Bibliothek in das Programm eingebunden. Dieses Einbinden wird Linken genannt und es geschieht nach dem kompilieren des Programms. Es wird zwischen drei Arten des Linkens unterschieden. Dem statischen Linken, dem festen Linken und dem dynamischen Linken Statische Bibliotheken Bei dem statischen Linken hängt ein sogenannter Linker der kompilierten Anwendung die benötigten Programmteile der Bibliotheken an. Weiterhin werden die entsprechende Verweise und Funktionsadressen angepasst, so dass die Anwendung danach den kompletten Programmcode enthält und beim Ausführen die statisch eingebundene Bibliothek nicht mehr benötigt. Bibliotheken die für das statische Linken vorgesehen sind werden statische Bibliotheken genannt. Das statische Linken führt zu einer immensen

11 2. GRUNDLAGEN 9 Abbildung 2.2: Statisches Binden einer statischen Bibliothek Redundanz, da die Bibliotheksfunktionen in allen Programmen physisch vorkommen, die sie verwenden. Dies hat nicht nur Nachteile für den benötigten Speicherplatz, sondern auch für die Wartbarkeit des Codes der Bibliotheken. Enthält beispielsweise eine Funktion einer statischen Bibliothek einen Fehler, dann ist der Fehler auch in allen Programmen enthalten, die diese Funktion statisch eingebunden haben. Für eine Behebung des Fehlers reicht es nicht die statische Bibliothek zu ändern, es müssen auch alle Programme neu kompiliert (und gelinkt) werden, die diese Funktion verwendenden. Der größte Vorteil vom statischen Linken ist, dass die Bibliothek zum Ausführen der Programme nicht mehr benötigt wird. Außerdem können der Kompiler und der Linker, beim erzeugen der fertigen Anwendung, den Programmierer auf nicht vorhandene Funktionen und auf Fehler bezüglich der Kompatibilität zwischen Anwendung und Bibliothek hinweisen Dynamische Bibliotheken Für eine Funktionsbibliothek eines Betriebssystem sind die Nachteile des statischen Linkens sehr gravierend, da sie Funktionen enthält, die von vielen Programmen benötigt werden. Da eine solche Funktionsbibliothek dem Betriebssystem angehört, ist sie sehr wahrscheinlich auch beim der Ausführung des Programms vorhanden. Dies ermöglicht einen späteren Zeitpunkt des Bindens der Bibliothek an das Programm. Bibliotheken die beim Ausführen (zur Laufzeit) eines sie nutzenden Programms gebunden werden, nennt man dynamische Bibliotheken. Diese Bibliotheken werden nur dann in den physischen

12 2. GRUNDLAGEN 10 Speicher (Arbeitsspeicher) geladen, wenn sie dort noch nicht vorhanden sind. Sie befinden sich also höchstens einmal im Hauptspeicher und verbleiben dort, bis alle sie verwendenden Prozesse beendet sind. Beim Binden an ein Programm wird die Bibliothek in dessen virtuellen Adressraum eingeblendet. Alle nicht statischen Datenbereiche der Bibliothek werden den entsprechenden Bereichen der Anwendung angegliedert. Sie sind für jeden Prozess der die Bibliothek nutzt, jeweils einmal im Adressraum des Prozesses zu finden. Deshalb können zwei Prozesse, welche gemeinsam eine Bibliothek nutzen, verschiedene Ausprägungen der gleichen, in der Bibliothek definierten, globalen Variable besitzen. Eine Kommunikation der Prozesse mit Hilfe dieser Variablen ist somit nicht möglich. Als Stackspeicher, wird von der Bibliothek der Stack des aufrufenden Prozesses genutzt. Der statische Teil einer dynamischen Bibliothek wird von allen Prozessen gemeinsam verwendet. Dafür wird dieser Bereich im Hauptspeicher von der Speicherverwaltung (memory management unit) vor einem Beschreiben geschützt. Der Maschinencode einer Bibliothek ist dadurch vor dem Überschreiben gesichert, kommt aber trotzdem maximal einmal im Hauptspeicher vor. Da die Bibliothek in den virtuellen Adressraum des aufrufenden Prozesses eingeblendet wird, sind beim Ausführen die Bibliotheksfunktionen genauso effektiv, wie von vornherein in die Anwendung eingebaute Funktionen. Sie besitzen aber automatisch auch die gleichen Rechte wie die Anwendung bzw. der Prozess selbst. Dynamische Bibliotheken können entweder fest oder dynamisch in eine Anwendung eingebunden werden. Beim festen Linken werden für die benötigten Funktionen (oder Daten) der Bibliothek Scheinobjekte (sogenannte stubs) erzeugt, damit für den Linker alle Referenzen erfüllt sind. Es sind also wie beim statischen Linken, alle Funktionsdefinitionen auch im Programm zu finden. Die Implementation ist hingegen nur in der Bibliothek enthalten. Beim Starten der Applikation wird die Bibliothek, wie zuvor beschrieben geladen und in den virtuellen Adressraum eingeblendet. Da das Linken beim Start des Programms erfolgt, also vor Ausführung des Programmcodes, kann die Anwendung auf mögliche Fehler beim Einbinden der Bibliotheken nicht reagieren. Fehlende Bibliotheken beispielsweise, haben immer einen Programmabbruch zur Folge. Wie beim statischen Linken, werden beim festen Linken, fehlende Funktionen und Probleme bei der Kompatibilität zwischen Anwendung und Bibliothek entdeckt und dem Programmierer beim Erstellen der Anwendung mitgeteilt. Die zweite Art der Bindung einer dynamischen Bibliothek ist das dynamische Binden. Dabei sind nach dem Kompilieren der Anwendung weder die Funktionsdefinitionen noch deren Implementation im Programm festgeschrieben. Das Laden der Bibliothek und das Einblenden in den virtuellen Adressraum geschieht analog zum festen Linken, allerdings wird beim dynamischen Linken der Zeitpunkt des Bindens vom Programmierer festgelegt. Dafür stellt das Betriebssystem Funktionen zum Laden und Entladen von Bibliotheken und zum Ermitteln der Einsprungadressen von Bibliotheksfunktionen oder Bibliotheksdaten bereit. Da das dynamische Linken vollkommen unabhängig vom Kompiler und vom Linker abläuft,

13 2. GRUNDLAGEN 11 muss der Programmierer allein dafür sorgen, dass die implizit angenommene Funktionsdefinition mit der Bibliotheksfunktion übereinstimmt. Dadurch wird es aber auch möglich auf Fehler beim Binden zu reagieren. Es könnte z. B. auf eine alternative Bibliothek zurückgegriffen werden, wenn die eigentliche Bibliothek nicht vorhanden ist. Dies ist beim festen Linken nicht möglich. Abbildung 2.3: Festes Binden einer dynamischen Bibliothek Windows und dynamische Bibliotheken In Windows Betriebssystemen werden dynamische Bibliotheken DLL (dynamic link library) genannt. Sie besitzen alle die Funktion DllMain, welche als Einsprungpunkt beim Laden und Entladen der DLL dient. Ihr wird als zweiter Parameter der Grund für den Aufruf übergeben. Wird DllMain vom Programmierer der DLL nicht implementiert, so wird eine Standard DllMain-Funktion erzeugt (für weitere Informationen siehe [12]). Die von Windows für das dynamische Binden bereitgestellten Funktionen sind LoadLibrary, FreeLibrary und GetProcAddress. Zum Laden wird LoadLibrary verwendet, welche bei Erfolg einen Verweis vom Typ HINSTANCE auf die geladene DLL zurückgibt. Dieser Verweis wird von GetProcAddress verwendet um einen Zeiger auf in der Bibliothek enthaltene Funktionen oder Daten zu bekommen. Diese können dann mit dem Zeiger ausgeführt bzw. ausgelesen und verändert werden.

14 2. GRUNDLAGEN 12 FreeLibrary blendet die DLL aus dem virtuellen Adressraum aus und veranlasst zudem das Löschen aus dem physischen Arbeitsspeicher, wenn sie von keinem anderen Prozess genutzt wird Linux und dynamische Bibliotheken Dynamische Bibliotheken werden in Linux shared objects genannt. Sie besitzen die Einsprungpunkte _init und _fini für das Laden bzw. Entladen der DLL. Werden diese vom Programmierer nicht implementiert, werden Standardversionen dieser Funktionen genutzt. Das Laden einer dynamischen Bibliothek erfolgt über die Betriebssystemfunktion dlopen. Auch hier wird ein Zeiger zurückgegeben der dann von dlsym genutzt werden kann, um einen Zeiger auf eine Funktion oder ein Objekt der Bibliothek zu erhalten. Durch dlclose wird die Bibliothek wieder aus dem virtuellen Adressraum entfernt und ggf. aus dem Hauptspeicher gelöscht. 2.4 Beispiele für Pluginsysteme In vielen kommerziellen, als auch freien Applikationen werden Pluginsysteme genutzt. Sie erweitern die bestehende Funktionalität, verändern das Aussehen oder führen komplett neue Funktionen in die Hostanwendung ein. Im Folgenden sollen einige Pluginsysteme vorgestellt und so Beispielhaft deren Nutzung in heutigen Anwendungen aufgezeigt werden Adobe Photoshop Plugins Im Bereich der Bildbearbeitung ist das Pluginsystem von Photoshop am verbreitetsten. Es wird nicht nur von Photoshop selbst, sondern auch von anderen Anwendungen (z. B. Paintshop Pro) zur Erweiterung genutzt. Auch innerhalb der Produktfamilie von Adobe können häufig die gleichen Plugins untereinander verwendet werden. Das Pluginsystem wurde von Adobe mit der Version 2.5 der Bildbearbeitungssoftware Photoshop [1] eingeführt. Für Pluginentwickler wird ein SDK (Software Development Kit) bereitgestellt, womit sich Plugins in C (später auch teilweise in C++) schreiben lassen. Diese Sammlung von Programmen und Dokumentationen war bis 2002 frei zugänglich und kostenlos. Seit 2002 ist die Nutzung des SDK kostenpflichtig. Von der Firma Centaurix wurde mittlerweile das Photoshop SDK für Delphi portiert [5]. Neben der Programmierung von Plugins mittels C/C++ bzw. Delphi, gibt es die Möglichkeit Plugins mit verschiedenen Hilfsprogrammen zu erstellen. Diese Programme nehmen dem Entwickler viele Aufgaben ab und verbergen den eigentlichen C/C++ Quellcode des Plugins. Sie werden zumeist für die Entwicklung freier Plugins genutzt. Einige Beispiele für diese Programme sind Filter Factory, Filter Formula

15 2. GRUNDLAGEN 13 und Filter Meister. Für die Erweiterung von Photoshop sind verschiedene Arten von Plugins verfügbar: Image Filter Dies ist wohl die häufigste Art von Plugin. Sie können Bilder in verschiedenster Weise verändern. Ein Beispiel für ein solches Plugin ist der Filter Wolken, welcher das ausgewählte Bild, unter Zuhilfenahme der Vordergrund- und Hintergrundfarbe, mit einem Wolkenmuster füllt. Import Mit einem solchen Plugin können neue Quellen bestimmt werden, aus denen sich Bilder zur Bearbeitung mit Photoshop importieren lassen. Export Neben dem Speichern von Bildern auf Festplatten, können durch ein Export Plugin auch andere Ziele (z. B. Drucker) definiert werden. Format Die von Photoshop unterstützen Grafikformate können mit dieser Art Plugin erweitert werden. Color Picker Hiermit lässt sich ein eigener Farbwahldialog designen und in Photoshop nutzen. Selection Um Photoshop eigene Auswahl-, Pfad- oder Ebenenfunktionen hinzuzufügen, kann ein Pluginentwickler diesen Plugintyp nutzen. Automation So ziemlich alle Menuaktionen und Tooloperationen lassen sich mit diesem Plugintyp automatisieren. Es können unter Anderem auch weitere Plugins gestartet werden. Extension und Parser Die Schnittstellen dieser Plugintypen sind nicht öffentlich. Solche Plugins werden nur von Adobe erstellt. Alle erstellten Plugins werden in entsprechende Verzeichnisse von Photoshop kopiert, wo sie beim Start der Anwendung gesucht werden. Photoshop prüft dabei für jedes Plugin ob es eine sogenannte plugin property list (PiPL) als Ressource enthält. Eine solche Liste stellt alle benötigten Informationen über das Plugin bereit. Diese Informationen werden von Photoshop auch zum Darstellen der Plugins im Menu genutzt. So kann z. B. für Filter der Untermenüpunkt festgelegt werden, unter welchem der Filter in Photoshop zu finden ist. Die Schnittstelle von Plugin und Hostanwendung ist sehr einfach gehalten. Von der Hostanwendung wird die Funktion main des Plugins zur Kommunikation genutzt. Die Art der Interaktion wird über ein Integerparameter bestimmt. Alle gemeinsam genutzten Daten werden über Zeiger auf die Datenbereiche mitgeteilt, welche als Parameter der Funktion main übergeben werden Qt Plugins Trolltechs API Qt unterstützt ebenfalls die Nutzung von Plugins. Qt stellt dabei eine Sammlung von Klassen, Funktionen und Makros bereit, die der Erstellung von Plugins und Hostanwendungen dienen. Eine Qt nutzende Anwendungen kann die Klasse QPluginLoader verwenden, um so durch Plugins erweitert

16 2. GRUNDLAGEN 14 werden zu können. Für ein Pluginsystem mit Qt müssen als Erstes die Schnittstellen definiert werden. Sie werden mit Hilfe von einem Makro Qt bekannt gemacht und können den Plugins als Basisklassen dienen. So erstellte Plugins können von einem QPluginLoader Objekt geladen und mit qobject_cast auf Schnittstellen getestet werden. Neben diesem Pluginsystems für Anwendungen, enthält die Qt Klassenbibliothek schon fertige Basisplugins, um Qt selbst zu erweitern. Für eigene Erweiterungen von Qt kann von diesen Plugins geerbt, eigene Funktionen hinzugefügt und dann mittels einem dafür vorgesehenen Makro das neue Plugin bei Qt registriert werden. Je nach gewähltem Basisplugin muss die neu geschriebene Erweiterung in ein spezielles Verzeichnis kopiert werden, damit Qt es nutzen kann. Sollen Applikationen weitergegeben werden, die eine so erweiterte Qt API nutzen, dann müssen die Plugins entweder statisch an das Programm gelinkt werden, oder mit der Applikation mitgeliefert und in entsprechende Verzeichnisse gesteckt werden. In Tabelle 2.1 werden alle vordefinierten Basisplugins und deren Standardverzeichnisse aufgelistet. Plugin QAccessibleBridgePlugin QAccessiblePlugin QDecorationPlugin QIconEnginePlugin QImageIOPlugin QInputContextPlugin QKbdDriverPlugin QMouseDriverPlugin QPictureFormatPlugin QScreenDriverPlugin QScriptExtensionPlugin QSqlDriverPlugin QStylePlugin QTextCodecPlugin Verzeichnis accessiblebridge accessible decorations iconengines imageformats inputmethods kbddrivers mousedrivers pictureformats gfxdrivers script sqldrivers styles codecs Tabelle 2.1: Qt Plugins

17 3. DIE PLUGIN API FÜR C Die Plugin API für C++ Wie bereits zuvor erwähnt, gibt es sowohl für C++ also auch für.net eine API. Im Folgenden werden die einzelnen Teile der API für die Programmiersprache C++ näher beleuchtet und deren Verwendung erklärt. Die Grundidee der C++ Plugin API besteht darin, dass eine Reihe von Schnittstellen definiert werden und jedes Plugin von den Schnittstellen erbt, die nach Außen sichtbar sein sollen, d. h. deren Funktionen das Plugin unterstützt und von der Hostanwendung genutzt werden können. Damit das Ansprechen verschiedener Plugins möglich wird, wurde eine Schnittstelle definiert, von der alle Plugins erben. Diese Schnittstelle ist iplugin_base. In der C++ Plugin API werden neben den Schnittstellen auch Klassen eingeführt, die zum Laden und Schreiben von Plugins nötig sind. Außerdem werden einige Typen deklariert, welche die Arbeit mit Plugins erleichtern sollen. Da es in C++ keine spezielle Schnittstellendeklaration gibt, werden hier einfache Klassen verwendet. Diese können aber wie Schnittstellen (interfaces) behandelt werden, weil C++ Mehrfachvererbung unterstützt, d. h. eine C++ Klasse aus mehreren Basisklassen bestehen. 3.1 Typenreflektion mit dynamic_cast Abbildung 3.1: Speicherlayout eines Plugins

18 3. DIE PLUGIN API FÜR C++ 16 Für alle Plugins, die mit Hilfe der hier vorgestellten C++ API erstellt wurden, gibt es eine gemeinsame Basisklasse. Dies ist die Schnittstelle iplugin_base. Da neben dieser Basisklasse ein Plugin von beliebigen anderen Klassen erben kann, wird ein Zeiger auf iplugin_base (piplugin_base) zum Ansprechen der Plugins genutzt. In Abbildung 3.1 ist beispielhaft das Speicherlayout eines C++ Plugins zu sehen. Um neben iplugin_base auch die anderen Schnittstellen (Basisklassen) ansprechen zu können, müssen zur Laufzeit der Typ und die Basisklassen für das Plugin bekannt sein. Allgemeiner Formuliert muss man zur Laufzeit für jedes Objekt die zugrunde liegende Klasse bzw. deren Eigenschaften ermitteln können. Dieses Konzept wird Typenreflektion oder auch RTTI (runtime type information - Typinformation zur Laufzeit ) genannt. Die Sprache C++ unterstützt Typenreflektion nur für polymorphe Objekte, d. h. sie müssen eine Instanz einer virtuellen Klasse sein und so zumindest eine virtuelle Methode besitzen. Der Grund für diese Voraussetzung ist, dass der C++ Kompiler jeder virtuellen Klasse einen Zeiger auf die sogenannte virtual function pointer table (vtbl) anfügt. Eine solche Funktionstabelle wird zur Laufzeit für jede virtuelle Klasse geführt. Der Operator dynamic_cast nutzt diese Tabelle für die Typenreflektion und bietet so eine generische Methode, um zur Laufzeit mögliche Basisklassen eines Typs zu ermitteln. Dynamic_cast kann außerdem mit einem Verweis (Zeiger oder Referenz) auf eine Teilklasse eines polymorphen Objekts, auf das Vorhandensein weiterer Teilklassen (Basisklassen) dieses Objektes testen. Er könnte also z. B. mit einem Zeiger auf die Schnittstelle iplugin_base eines Plugins testen, ob dieses Plugin auch die Schnittstelle irenderable implementiert. Um das zu realisieren versucht dynamic_cast den Verweis eine Teilklasse in einen Verweis auf die andere Teilklasse des gleichen polymorphen Objekts zu wandeln. Für die Typumwandlung wird der dynamische Typ eines Verweises geprüft, und die Wandlung nur dann ausgeführt, wenn sie erlaubt ist. Dem Beispiel von weiter oben folgend würde dynamic_cast also erst den Typ des Plugins ermitteln, zu welchem die Teilklasse gehört, auf welche piplugin_base zeigt und dann testen ob dieser Plugintyp in die Schnittstelle irenderable umgewandelt werden kann. Ist der Verweis ein Zeiger wird bei einer unerlaubten Wandlung von Typen ein Nullzeiger zurückgegeben. Wird eine Referenz als Verweis genutzt, wirft dynamic_cast im Fehlerfall eine Ausnahme vom Typ bad_cast. [3] Quelltext A.1 zeigt die Verwendung von dynamic_cast. 3.2 Schnittstellendefinitionen in PluginDefs Damit die Hostanwendung und die Plugins kommunizieren können, müssen die Schnittstellen zwischen Beiden definiert werden. Diese Definition muss an zentraler Stelle erfolgen und sowohl vom Plugin als auch von der Hostanwendung unabhängig sein. In der C++ Plugin API sind alle Schnittstellendefinitionen in der statische Bibliothek PluginDefs enthalten. Alle dort definierten Schnittstellen können bei der Entwicklung von Plugins verwendet werden. Da C++ wie bereits erwähnt keine spezielle Deklaration für

19 3. DIE PLUGIN API FÜR C++ 17 Schnittstellen vorsieht, sind alle Schnittstellen virtuelle Klassen,die von plugin_interface_class erben. Außer der Standardschnittstelle iplugin_base sind alle Schnittstellen nicht abstrakt, obwohl dies dem Charakter einer Schnittstelle am ehesten entsprechen würde. Es brächte aber einige Nachteile mit sich, wenn sie alle abstrakt wären, denn es ist in C++ nicht möglich eine Liste von Typen zu erzeugen. Eine solche Liste wird aber z. B. beim Laden eines Plugins benötigt, um die Schnittstellen anzugeben, die ein zu ladendes Plugin implementieren soll (siehe dafür Kapitel 3.3.1). Durch den Verzicht auf abstrakte Schnittstellenklassen können nun Instanzen der einzelnen Schnittstellen in eine Liste gesteckt werden. Eine solche Liste die Schnittstellen aufnehmen kann ist in der C++ Plugin API bereits definiert und heißt plugin_interface_list Plugin_interface_class Die abstrakte Klasse plugin_interface_class ist die Basisklasse aller Plugin-Schnittstellen der API. Über sie können alle Schnittstellen angesprochen werden und wie bereits erwähnt in einer Liste zusammengefasst werden. Wie im Quelltext A.2 zu sehen wird in der Klasse die abstrakte Boolesche Funktion is_implemented_by definiert, welche von allen erbenden Schnittstellen implementiert werden muss. Die Funktion bestimmt für ein übergebenes Plugin, ob dieses die aktuelle Schnittstelle unterstützt. Um zu testen, ob ein Plugin eine Schnittstelle unterstützt, muss als Erstes eine Instanz der Schnittstelle erstellt werden und dann der Methode is_implemented_by dieser Schnittstelle, das Plugin als Parameter übergeben werden. Im Normalfall wird in der Funktion zum Testen eine Umwandlung mittels dynamic_cast von dem übergebenen Plugin zur Schnittstelle durchgeführt. Scheitert diese Umwandlung, wird von is_implemented_by false zurückgegeben. Im Erfolgsfall liefert die Funktion ein true zurück. In der Verwaltungsklasse plugin_loader wird is_implemented_by z. B. zum selektiven Laden der Plugins genutzt, die bestimmte Schnittstellen beinhalten Iplugin_base Für den ersten Zugriff auf ein Plugin wird die Standardschnittstelle iplugin_base genutzt. Sie ist eine Schnittstelle, die von allen Plugins implementiert werden muss. In ihr ist die abstrakte Funktion get_plugin_name angegeben. Sie ermöglicht es dem Plugin einen Namen zu geben. Daneben wird die ebenfalls abstrakte Funktion create_new_instance definiert, welche einen Zeiger vom Typ piplugin_base auf eine neue Instanz eines Plugins zurückliefert. Genau wie die Methode get_plugin_name muss auch create_new_instance vom Entwickler eines Plugins implementiert werden. Zumeist wird dies in der Pluginfabrik passieren (siehe dafür Kapitel 3.4.2). Neben der Klasse iplugin_base wird mit piplugin_base ein Zeiger auf eine Instanz dieser Klasse definiert. Weiterhin kann iplugin_pointer_list dazu genutzt

20 3. DIE PLUGIN API FÜR C++ 18 werden um Plugins in einer Liste zu speichern. Der Quelltext A.3 zeigt den Header der iplugin_base Schnittstelle Irenderable Für alle Plugins die auf irgendeine Weise, Inhalte in der Hostanwendung grafisch ausgeben wollen, ist die Schnittstelle irenderable gedacht. Plugins, die von irenderable erben, können über die Funktion render angesprochen werden. Diese Funktion wird vom Plugin implementiert und sollte eine grafische Ausgabe bewirken. Sie kann dann immer aufgerufen werden,wenn die Hostanwendung neu gezeichnet werden muss. Die Schnittstelle irenderable beinhaltet keine Einschränkung bezüglich der Art der grafischen Ausgabe. Die render Methode könnte jede beliebige Systembibliothek zum Zeichen verwenden. Für Hostanwendungen die verschiedene Systembibliotheken zur Ausgabe von Daten nutzen kann, ist es deshalb ratsam in einem Plugin mit grafischer Ausgabe, neben irenderable noch eine weitere Schnittstelle zu implementieren, welche die Art der Ausgabe genauer spezifiziert. Dadurch kann beim Laden eines Plugins festgelegt werden, was für Systembibliotheken zur Darstellung von Inhalten von der Hostanwendung unterstützt werden. Ein Plugin könnte z. B. zusätzlich die Schnittstelle id3d9_plugin implementieren. Beim Laden dieses Plugins würde das Pluginsystem dann feststellen können, dass die grafische Ausgabe mit Direct3D 9 durchgeführt wird Id3d9_plugin Die Schnittstelle id3d9_plugin ist für Plugins gedacht, die mit Direct3D 9 auf einen Bereich der Hostanwendung zeichnen möchten. Die Hostanwendung ist also für die Initialisierung von Direct3D 9 zuständig, d. h. unter anderem für das Erstellen eines IDirect3DDevice9 Objektes, welches die Zeichenfläche für Direct3D 9 darstellt. Ein solches Objekt wird in Direct3D 9 von allen Funktionen benötigt, die etwas darstellen wollen. Deswegen muss es auch einem Plugin zur Verfügung stehen, welches grafische Objekte mittels Direct3D 9 ausgeben möchte. Für dieses Problem enthält id3d9_plugin die Funktion init_d3d9. Sie besitzt als Parameter einen Standardzeiger vom Typ void. Der Zeiger ist nicht näher typisiert, weil es sonst feste Abhängigkeiten zwischen der Plugin API und den DirectX Bibliotheken gäbe. Es ist vorgesehen, dass dieser Zeiger auf ein IDirect3DDevice9 Objekt zeigt, welches in der Hostanwendung erstellt wurde. Dieser Zeiger kann vom Plugin gespeichert werden und ihm so Zugriff auf das benötigte IDirect3DDevice9 Objekt bieten. Mit init_d3d9 kann das Plugin außerdem alle für seine grafischen Ausgaben notwendige Objekte erstellen. Um diese Objekte wieder freizugeben, kann release_d3d9 verwendet werden.

21 3. DIE PLUGIN API FÜR C++ 19 Eine Hostanwendung die Plugins unterstützt, welche die id3d9_plugin Schnittstelle implementieren, muss sich darum kümmern, dass die Funktionen init_d3d9 und release_d3d9 an den notwendigen Stellen aufgerufen werden IPluginEventCallback Bei einigen Anwendungen des Pluginsystems kann es notwendig sein, dass die Hostanwendung auf bestimmte Ereignisse in einem Plugin reagiert. Beispielsweise könnte ein Plugin der Hostanwendung signalisieren, dass Teile von einer Datenmenge fertig bearbeitet wurden und bereit sind von der Hostanwendung ausgegeben zu werden. Für solcher Art Plugins ist die Schnittstelle iplugin_event_callback gedacht, deren Aufbau im Quelltext A.4 zu sehen ist. Sie führt die zwei bereits implementierten Methoden set_event_callback und do_event ein, welche einem Plugin die Möglichkeit bieten, zur Ereignisbehandlung eine Funktion der Hostanwendung zu nutzen. Eine solche Funktion in der Hostanwendung wird in der Programmierung callback Funktion genannt, weil sie im Plugin zurückgerufen werden kann. Sie muss dem von cplugin_event_callback festgelegten Typ entsprechen, d. h. sie besitzt keinen Rückgabewert und hat als einzigen Parameter den Aufzählungstyp enum_plugin_event. Durch die Methode set_event_callback wird sie für die Behandlung von Ereignissen im Plugin festgelegt. Dies wird erreicht, indem set_event_callback den private Funktionszeiger cfpdo_event auf die als Parameter übergebene callback Funktion setzt. Tritt im Plugin ein Ereignis ein, dass gemeldet werden soll, muss die private Schnittstellenmethode do_event vom Plugin aufgerufen werden. Diese stößt wiederum die Hostfunktion an, auf die von cfpdo_event gezeigt wird. Dadurch wird das Ereignis nach Außen bekannt zu geben, und kann in der callback Funktion behandelt werden. Die Art des Ereignisses wird aus einer Aufzählung vom Typ enum_plugin_event bestimmt und als Parameter der callback Funktion mitgeteilt Ikeyboard_event_handler In den meisten Bereichen, in denen Plugins benutzt werden, kümmert sich die Hostanwendung um die Interaktion mit dem Benutzer. Tastatureingaben und andere Ereignisse werden in dafür vorgesehenen Funktionen behandelt. Mit Hilfe der Schnittstelle ikeyboard_event_handler können die Tastaturereignisse an ein Plugin weitergegeben werden, wodurch dieses dann auf das übergebene Ereignis reagieren kann. In der Schnittstelle werden drei Arten von Tastaturereignissen unterschieden. Wird eine Taste herunter gedrückt kann dies mit der Methode on_key_down dem Plugin mitgeteilt werden. Durch on_key_up erfährt das Plugin, dass eine Taste wieder losgelassen wurde. Wurde eine Taste gedrückt und wieder losgelassen, wird dies durch on_key_press dem Plugin übergeben. Allen drei Methoden wird die gedrückte Taste als Parameter übergeben. Dafür wird der Aufzählungstyp xp_key_code verwendet.

22 3. DIE PLUGIN API FÜR C Imouse_event_handler Wenn Plugins auf Mausereignisse reagieren sollen, kann imouse_event_handler implementiert werden. Genau wie bei der Schnittstelle ikeyboard_event_handler, werden hier die von der Hostanwendung aufgefangenen Ereignisse, an das Plugin weitergegeben. Die Methode on_mouse_button_down meldet dem Plugin, dass ein Mausknopf herunter gedrückt wurde. Dagegen kann ein losgelassener Knopf mit on_mouse_button_up bekannt gemacht werden. Durch on_mouse_move werden Mausbewegungen mitgeteilt. Um einen Mausklick weiterzugeben wird on_mouse_click genutzt und für Doppelklicks ist on_mouse_dbclick zuständig. Als Parameter wird ein Wert vom Aufzählungstyp xp_mouse_button und die Mauskoordinaten als int erwartet. 3.3 Die Verwaltungsklasse plugin_loader In einer Hostanwendung gibt es in Bezug auf Plugins drei wichtige Aufgaben. Die Plugins müssen dynamisch geladen werden können, der Zugriff auf die geladenen Plugins muss schnell und einfach vonstatten gehen und nicht mehr benötigte Plugins müssen auch wieder entfernbar sein. Um dem Entwickler einer Hostanwendung diese Dinge abzunehmen, enthält die C++ Plugin API die Verwaltungsklasse plugin_loader, welche für jede der einzelnen Aufgaben passende Methoden bereitstellt. Die Hostanwendung muss nun nur noch ein Objekt aus der Klasse erzeugen und kann dann mit dessen Hilfe Plugins nutzen. Der Quelltext A.5 zeigt den Header der Verwaltungsklasse plugin_loader. Da das Laden und Entladen von Plugins das dynamische Binden bzw. entfernen von Bibliotheken beinhaltet, ist plugin_loader auf die in Kapitel und beschriebenen Systemfunktionen angewiesen. Damit die Plattformunabhängigkeit der Klasse gewährleistet bleibt, werden statt den systemspezifischen Funktionen, die in den Dateien CrossPlattform.h und CrossPlattform.cpp, für Linux und Windows implementierten, plattformunabhängigen Funktionen xp_load_library, xp_get_proc_address und xp_free_library genutzt. Zum Laden dynamischer Bibliotheken wird xp_load_library verwendet. Diese gibt ein xp_dll_handle zurück, welches zur Identifizierung der geladenen Bibliothek dient. Ein solches xp_dll_handle wird z. B. von der Methode xp_get_proc_address benötigt. Diese Methode wird dazu genutzt, um in der zum übergebenen xp_dll_handle passenden dynamischen Bibliothek, die Einsprungadresse der Funktion get_plugin_factory_list zu finden. Auf den Nutzen dieser Funktion und weitere Einzelheiten zum Laden von Plugins wird in Kapitel genauer eingegangen. Sind alle Plugins einer Bibliothek nicht mehr in Gebrauch, kann die Bibliothek mit xp_free_library entladen werden. Welche Bibliothek freigegeben werden soll, wird durch den Parameter vom Typ xp_dll_handle bestimmt.

23 3. DIE PLUGIN API FÜR C Laden neuer Plugins Wie bereits erwähnt, wird dem Entwickler durch die Klasse plugin_loader u. a. das Laden von Plugins vereinfacht. Dafür ist die überladene Methode load zuständig. Wie der Quelltext A.5 zeigt ist dazu immer der Name der Pluginbibliothek inklusive dem Pfad erforderlich. Optional kann außerdem eine Liste von Schnittstellen übergeben werden. In der Methode wird zuerst die angegebene dynamische Bibliothek durch die plattformunabhängige Funktion xp_load_library geladen. Das zurückgegebene xp_dll_handle wird in einer Struktur vom Typ plugin_list_item gespeichert. Diese enthält neben dem xp_dll_handle noch einen Zeiger auf ein geladenes Plugin. Der Zeiger ist wie üblich vom Typ piplugin_base. Nach dem Laden der Bibliothek wird ein Funktionszeiger definiert, welchen xp_get_proc_address anschließend auf die Einsprungadresse der C -Funktion get_plugin_factory_list setzt. Diese Funktion wird vom Entwickler einer Pluginbibliothek implementiert, und gibt eine Referenz auf eine Liste sogenannter Pluginfabriken zurück (siehe Kapitel 3.4). Nachdem xp_get_proc_address erfolgreich den Funktionszeiger gesetzt hat, wird dieser zum Ausführen der zugewiesenen C -Funktion genutzt. Dadurch erhält man die oben erwähnte Referenz und kann mit ihrer Hilfe die Plugins der Bibliothek erzeugen, welche die geforderten Schnittstellen unterstützen. Wurde der Methode load keine Liste von notwendigen Schnittstellen übergeben, werden alle Plugins aus der Bibliothek erzeugt. Zum Abschluss werden Zeiger auf diese Plugins in der Struktur vom Typ plugin_list_item gespeichert, und dann zusammen mit dem zugehörigen xp_dll_handle in die Liste m_plugin_list vom Typ plugin_list eingetragen, welche der Klasse plugin_loader angehört. Soll ein Plugin vor dem Programmende aus dieser Liste entfernt werden, kann man entweder die Methode delete_plugin der Klasse plugin_loader verwenden, oder direkt auf die Liste zugreifen und deren Methode zum Löschen verwenden Pluginliste Von der Klasse plugin_loader geladene Plugins werden in einer Liste vom Typ plugin_list gespeichert. Diese Liste heißt m_plugin_list, ist öffentlich und kann so wenn nötig über das plugin_loader Objekt direkt angesprochen werden. Im Normalfall wird sie aber nur von den Methoden der Klasse plugin_loader genutzt. Auf den Zugriff und den Umgang mit Plugins wird im folgenden Kapitel näher eingegangen. Ein Element der Liste plugin_list ist durch plugin_list_item beschrieben. Es enthält einen Zeiger auf eine Plugininstanz und einen Verweis (Handle) auf die dazugehörigen Bibliothek. Wie der Quelltext A.6 zeigt, werden intern diese Listeneinträge in einem vector gespeichert. Das Hinzufügen von Einträgen geschieht durch die Methode add_item. Ihr werden die neuen Einträge mittels einem als Parameter übergebenen plugin_list_item mitgeteilt. Die Klasse plugin_loader nutzt sie beim Laden der Plugins aus

24 3. DIE PLUGIN API FÜR C++ 22 einer Bibliothek. Das Entfernen von bestehenden Elementen erfolgt durch delete_item. Dieser Methode wird der Index des zu löschenden Listeneintrags, als Parameter überliefert. Beim Löschen von Einträgen, kümmert sich die Klasse plugin_list auch darum, dass neben der Plugininstanz die zugehörige Bibliothek aus dem Speicherbereich der Hostanwendung ausgeblendet (entladen) wird, wenn kein anderes Plugin dieser Bibliothek in der Liste vorhanden ist. Durch Aufruf des Destruktors der Listenklasse, also beim Freigeben des Objektes, werden automatisch alle Elemente der Liste mit Hilfe von delete_item gelöscht. Um ein bestimmtes Plugin aus der Liste anzusprechen, nutzt plugin_loader die Methode get_plugin, welche einen Zeiger vom Typ piplugin_base zurückgibt. Durch plugin_count wird die Anzahl der in der Liste enthaltenen Plugins zurückgegeben Zugriff auf Plugins Neben Methoden zum Laden und Entfernen von Plugins, bietet plugin_loader auch Möglichkeiten zum Zugriff auf die geladenen Plugins. Die Pluginliste m_plugin_list ist zwar wie bereits erwähnt öffentlich und somit auch direkt ansprechbar, allerdings gestaltet sich der Zugriff durch die vom plugin_loader bereitgestellten Funktionen etwas einfacher. Diese Funktionen sind zum Einem get_plugin und zum Anderen get_interface. Genau wie bei der gleichnamigen Methode der Klasse plugin_list, wird auch hier get_plugin der Index des gewünschten Plugins übergeben und ein Zeiger auf die iplugin_base Basisklasse des Plugins zurückgeliefert. Dieser Zeiger kann dann mit Hilfe von dynamic_cast in andere Schnittstellen umgewandelt werden. Eine andere Möglichkeit des Zugriffs bietet die inline Schablonenmethode get_interface. Ihr wird als Schblonenparameter eine gewünschte Schnittstelle übergeben. Der als Funktionsparameter angegebene Index, bestimmt das Plugin aus der Liste, für welches der Zugriff auf die angegebene Schnittstelle gewährt werden soll. Wie im Quelltext A.5 zu sehen ist, führt get_interface dann eine Typumwandlung mittels dynamic_cast durch, und liefert einen Zeiger zurück, der auf die geforderte Schnittstelle zeigt. Enthält das Plugin keine solche Schnittstelle, wird ein Nullzeiger zurückgegeben. Der Quelltext A.7 zeigt den Umgang mit beiden Methoden. 3.4 Plugin Bibliotheken schreiben Das Schreiben von Plugins, die durch Klassen der hier vorgestellten API genutzt werden sollen, gestaltet sich kaum unterschiedlich zum Schreiben normaler Anwendungen. Da Plugins im Speicherbereich des aufrufenden Prozesses ausgeführt werden, besitzen sie die gleichen Rechte und Einschränkungen wie zu dem Prozess gehörende Funktionen. Ein wichtiger Unterschied besteht allerdings darin, dass ein Plugin

25 3. DIE PLUGIN API FÜR C++ 23 selten alleine in der Hostanwendung agiert. Das bedeutet, dass je nachdem wie stark die Plugins in eine Anwendung eingreifen, sich auch indirekt der Einfluss der Plugins untereinander erhöht. Nutzt beispielsweise ein Plugin die Funktionen von OpenGL zur grafischen Ausgabe, so bleiben die dafür benötigten Änderungen an OpenGL (z. B. Lichteinstellungen, Farben o. Ä.) innherhalb der gesammten Hostanwendung erhalten. Ein weiteres, OpenGL nutzendes Plugin, könnte also dadurch beeinflusst werden und so seine Daten nicht wie gewünscht ausgeben. Ein Plugin sollte deshalb nur soviel wie unbedingt nötig an Eigenschaften der Hostanwendung ändern und soweit wie möglich die unerwünschten, aber für die Funktion des Plugins notwendigen, Änderungen nach der Ausführung des Plugins wieder rückgängig machen. Damit Plugins von einer Instanz der Klasse plugin_loader geladen werden können, müssen sie vom Pluginentwickler in eine dynamische Bibliotheken geschrieben werden. Eine solche Bibliothek kann im Prinzip eine beliebige Zahl an Plugins enthalten. Für das Laden ist es nötig das alle enthaltenen Plugins an zentraler Stelle registriert sind. Dazu dient eine Verwaltungsklasse vom Typ plugin_factory_list_class, auf welche im folgenden Kapitel genauer eingegangen wird. Damit eine Hostanwendung Zugriff auf diese Liste bekommt, muss eine Pluginbibliothek die Funktion get_plugin_factory_list exportieren. Diese Funktion wird als C -Funktion deklariert, damit der Compiler kein name mangeling durchführt. Das name mangeling ist eine Bezeichnung für die Umbenennung von Funktionen durch den C++ Kompiler. Der neue Name wird unter Einbeziehung des Funktionsnamen und der Funktionsparameter gebildet. Der Grund für die Umbenennung durch den Kompiler liegt darin, dass C++ Funktionen überladen werden können, d. h. dass es möglich ist, sie mit jeweils unterschiedlichen Parametern mehrfach zu implementieren. Dadurch ist aus dem Funktionsnamen allein nicht eindeutig zu schließen welche Implementation dieser Funktion gemeint ist. Da aber Symbole, also Funktionen und andere globale Objekte in einer kompilierten Datei, über den Namen angesprochen werden, muss der C++ Kompiler die Funktionsnamen wie oben beschrieben erweitern. Leider gibt es keinen Standard für diese Umbenennung. Der Symbolname einer C++ Funktion kann also je nach Kompiler variieren. Da Plugins mit unterschiedlichen C++ Kompilern geschrieben worden sein können, der Name der Funktion aber vorher bekannt und überall gleich sein soll, wird get_plugin_factory_list also als C -Funktion deklariert. In C gibt es keine Möglichkeit zum überladen von Funktionen und es findet darum auch kein name mangeling statt plugin_factory_list_class Wie zuvor erwähnt, exportiert jede Pluginbibliothek eine Funktion get_plugin_factory_list. Sie gibt eine Referenz auf eine Instanz der Klasse plugin_factory_list_class zurück. Diese stellt wiederum eine

26 3. DIE PLUGIN API FÜR C++ 24 Liste dar, welche für jedes Plugin der Bibliothek eine sogenannte Pluginfabrik (siehe Kapitel 3.4.2) enthält. Sie führt die Funktion create_plugin ein, welche ein ausgewähltes Plugin mit Hilfe der zugehörigen Fabrik erstellt. Welches Plugin zu erstellen ist, wird über einen als Parameter übergebenen Index festgelegt. Neben dieser Funktion kann create_all_plugins genutzt werden, um mehrere Plugins der Bibliothek zu erstellen. Ihr werden zwei Listobjekte als Parameter übergeben. Die erste Liste ist bei der Übergabe leer und wird von der Funktion mit Zeigern auf die erstellten Plugins gefüllt. Diese Zeiger sind vom Typ piplugin_base, zeigen also auf die Standardschnittstelle iplugin_base des erstellten Plugins. Die zweite Liste, die von create_all_plugins verlangt wird, enthält Instanzen aller Schnittstellen, welche das zu erzeugende Plugin implementieren soll. Sie dient also als Filter, um nicht alle Plugins einer Bibliothek in eine Hostanwendung aufnehmen zu müssen. Wird eine leere Liste übergeben, werden dementsprechend alle Plugins der Bibliothek geladen. Sowohl create_all_plugins als auch create_plugin werden im Normalfall nicht direkt vom Entwickler aufgerufen. Die Klasse plugin_loader nutzt sie zum Laden der Plugins (siehe auch Kapitel 3.3.1). Eine typische Pluginbibliothek enthält genau eine globale Instanz der Klasse plugin_factory_list_class, von welcher mit der oben beschriebenen Funktion, eine Referenz an die Hostanwendung übergeben wird. Dieser Instanz müssen alle Plugins der Bibliothek bekannt gemacht werden. Dafür ist die Schablonenfunktion register_factory vorgesehen. Ihr wird mittels Schablonenparameter eine Pluginfabrikklasse übergeben. Aus dieser erzeugt die Funktion eine Instanz, die sie dann in der Liste m_class_factory_list speichert. Im Quelltext A.8 ist die Listenklasse und die Implementation der Schablonenfunktion register_factory zu sehen Pluginfabriken Will man eine Pluginbibliothek schreiben, die mit den hier vorgestellten Klassen kompatibel ist, muss für jedes Plugin, welches der Bibliothek hinzugefügt wird, auch eine Pluginfabrik vorhanden sein. Eine solche Klassenfabrik (engl. class factory) ist in der Lage, Instanzen des ihr zugeordneten Plugins zu erzeugen. Sie erben von den gleichen Schnittstellen wie das Plugin, was sie erzeugen wollen, implementieren aber die Schnittstellenmethoden nicht neu. Eine Ausnahme bildet die abstrakte Standardschnittstelle iplugin_base. Sie zwingt den Pluginentwickler dazu, die Beiden für die Fabrik wesentlichen Methoden zu implementieren. Die Eine ist get_plugin_name und liefert den Namen des zu erstellenden Plugins zurück. Die Andere ist create_new_instance. Sie ist für das eigentliche erstellen des Plugins zuständig. In Pluginbibliotheken werden Pluginfabriken in eine Liste eingetragen um einer Hostanwendung, welche die jeweilige Bibliothek aufruft, mitteilen zu können, welche Plugins in der Bibliothek enthalten sind (siehe Kapitel 3.4.1). Hierzu werden nicht die Plugins selbst gelistet, weil die Fabriken sowohl

27 3. DIE PLUGIN API FÜR C++ 25 weniger Speicherplatz benötigen, als auch meist schneller zu erzeugen sind als die zugehörigen Plugins. Trotzdem besitzen sie die zum Laden von Plugins nötigen Informationen über unterstütze Schnittstellen sowie den zur Identifikation der Plugins nützlichen Pluginnamen. Die Plugin API verlangt von Pluginfabriken, dass sie die gleichen Schnittstellen besitzen wie das von ihnen erzeugte Plugin selbst. Dies kann dadurch erreicht werden, dass das Plugin allein von der Fabrik erbt. Es müsste dann auch die beiden Funktionen der Standardschnittstelle iplugin_base nicht erneut implementieren, da dies bereits in der Basisklasse, der Pluginfabrik, geschehen ist. Der Pluginentwickler ist aber nicht dazu gezwungen so vorzugehen. Er könnte einem Plugin auch weitere Basisklassen zuweisen. Es ist aber zu beachten, dass eine Hostanwendung immer nur die Schnittstellen der Pluginfabrik abfragen kann, nicht die des Plugins.

28 4. DIE PLUGIN API FÜR.NET 26 4 Die Plugin API für.net Will man Pluginsysteme in.net verwenden, kann die C++ API nicht genutzt werden. Aus diesem Grund wurden die Klassen der C++ API für eine.net Version umgeschrieben. Dafür wurde die Programmiersprache C# verwendet. Die entstandene API kann aber auch von allen anderen managed Sprachen benutzt werden. Für eine Zusammenarbeit von C++ und.net Komponenten, muss der Entwickler eine gemischte Anwendung schreiben, d. h. eine Anwendung mit einen native Teil und einem managed Teil und auch allein die Kommunikation der beiden Teile bewältigen (siehe auch Kapitel 2.2.3). Die Klassennamen und Funktionen wurden weitgehend übernommen und auch der sonstige Aufbau des.net Teils der Plugin API gleicht dem der C++ Plugin API sehr. Sie enthält ebenfalls eine Reihe von Schnittstellen, die von Plugins implementiert werden können. Daneben enthält sie die Verwaltungsklasse plugin_loader die wie in C++ für das Laden und Löschen der Plugins, sowie für den Zugriff auf die geladenen Plugins zuständig ist. Weil es in.net möglich ist, aus einem Assembly alle vorhandenen Typen auszulesen, sind für das Erstellen von Pluginbibliotheken (Assemblies) keine Pluginfabriken notwendig. Dadurch gestaltet sich der Aufbau der Bibliotheken etwas einfacher als in C++. Die Plugins können ohne zusätzlichen Aufwand direkt in ein Assembly geschrieben werden. Diese Art von Assembly wird in C# Klassenbibliothek genannt. 4.1 Typenreflektion im.net Framework Im.NET Framework wird die Typenreflektion durch das Assembly System.Reflection bewerkstelligt. Dieses besteht, wie Abbildung 4.1 zeigt, aus verschiedenen APIs. Für die Typenreflektion sind primär die Info APIs von Bedeutung. Die Info APIs erlauben den Zugriff auf das Typensystem von.net. Mit ihrer Hilfe können dynamisch Objekte erstellt, Methoden aufgerufen und Objekteigenschaften verändert werden, ohne das der Typ beim Kompilieren bekannt ist. Außerdem können jegliche Informationen über ein Assembly (die sogenannten Metadaten) ausgelesen werden. Diese Metadaten stehen neben dem Zwischencode in jedem Assembly und enthalten Tabellen zu verwendeten Klassen, Felder usw. Enthält das Assembly z. B. fünf Klassen, so hat die Klassentabelle in den Metadaten fünf Zeilen. Die Tabellen können auf weitere Tabellen verweisen und so beispielsweise alle Methoden einer Klasse zeigen.

29 4. DIE PLUGIN API FÜR.NET 27 Die Info APIs stellen verschiedene Klassen für den Zugriff auf die Metadaten bereit. Die Klassen Assembly und Module bieten Zugriff auf wiederverwendbare Codesammlungen und ausführbare Assemblies. Type gibt Informationen über einzelne Typen der CLR preis. Zusätzlich sind die Klassen ConstructorInfo, MethodInfo, FieldInfo, PropertyInfo, EventInfo und ParameterInfo vorhanden, welche weitere Informationen über das Typensystem liefern. In den meisten Fällen werden die Info APIs zum Auslesen der Metadaten von Assemblies und Typen benötigt. Für Informationen über ein Assembly wird die Assembly Klasse genutzt. Eine Instanz dieser Klasse kann sowohl aus Informationen bereits geladener Assemblies erstellt werden, als auch beliebige Assemblies von einem Datenträger oder aus einem Datenstrom laden und deren Metadaten zurückliefern. Für die Plugin API ist vor allem das Laden von Assemblies von einem Datenträger interessant. Dafür können die statische Memberfunktionen Load, LoadFrom und LoadFile der Assembly Klasse genutzt werden. Load benötigt einen aussagekräftigen Namen des zu ladenden Assembly, d. h. das Assembly muss der Anwendung bekannt sein. Um Assemblies von der Festplatte oder sogar aus einem Netzwerk zu Laden, muss auf LoadFrom oder LoadFile zurückgegriffen werden. Diese beiden Funktionen unterscheiden sich nur wenig. Beiden wird ein string übergeben, der den Namen des Assembly und optional den Pfad enthält. Das so spezifizierte Assembly wird dann geladen und das Assembly Objekt mit den Metadaten gefüllt. Der Hauptunterschied ist, dass LoadFrom verschiedene Verzeichnisse nach bereits geladenen Assemblies durchsucht, welche mit dem zu ladenden Assembly übereinstimmen. Wird ein Assembly gefunden, nutzt LoadFrom dieses, anstatt erneut ein Assembly zu laden. Trotzdem kann es bei beiden Funktionen vorkommen, dass das gleiche Assembly mehrfach geladen wird, auch wenn dies mit LoadFrom seltener passiert. Aus diesem Grund wird in der Plugin API auch LoadFrom genutzt. Für die Verwendung von Assemblies in der Plugin API ist es wichtig zu wissen welche Klassen (Plugins) enthalten sind. Mit der Methode GetTypes kann dies erreicht werden. Sie liefert ein Array von Type Objekten zurück, welche den im Assembly enthaltenen Typen entsprechen. Jedes dieser Type Objekte kann auf das Vorhandensein von Schnittstellen getestet werden. Dies wird auch beim Laden von Plugins durch die Plugin API genutzt. Hier wird für jedes Type Objekt im Array mit der Funktion GetInterfaces eine Liste der implementierten Schnittstellen angefordert und mit der Liste der erwünschten Schnittstellen verglichen. Um von bestimmten Typen des Assembly Instanzen zu bilden, kann die Funktion CreateInstance des Assembly Objekts genommen werden. Sie erfordert in der einfachsten Überladung nur einen ausagekräftigen Namen des Typs. Üblicherweise wird die Eigenschaft FullName des Type Objekts zur Namensübergabe verwendet. Auf diese Art können Plugins in Assemblies verpackt und von der Plugin API geladen werden.

30 4. DIE PLUGIN API FÜR.NET 28 Abbildung 4.1: Überblick der System.Reflection APIs ([7]) 4.2 Schnittstellen in PluginDefs Das Assembly PluginDefs enthält alle Schnittstellendefinitionen der Plugin API für.net. Sie dienen, genau wie in der C++ API, der Kommunikation zwischen Hostanwendung und Plugin. Im Unterschied zu C++, unterstützt C# das Konzept von Schnittstellen. In C# ist dafür das Schlüsselwort interface vorgesehen. Schnittstellen werden im Grunde genau wie abstrakte Klassen in C++ deklariert. Zusätzlich dürfen sie aber auch keine Membervariablen enthalten. Eine C# Schnittstelle besteht also allein aus Deklarationen von Methoden, Eigenschaften, Indexers, die es erlauben auf Elemente der implementierenden Klasse mittels Index zuzugreifen (z. B. klassen_element[1];) und Ereignissen. Da es in.net möglich ist Typen in Listen zusammenzufassen und als Parameter zu übergeben, müssen die Schnittstellen auch nicht mehr instanzierbar sein. Darüberhinaus erben, aufgrund des wohldefinierten Typensystems von

31 4. DIE PLUGIN API FÜR.NET 29.NET, alle Schnittstellen von System.Object und nicht mehr von plugin_interface_class, wodurch auch die für.net überflüssige Methode is_implemented_by weg fällt. Quelltext A.9 zeigt beispielhaft an iplugin_base, wie in C# Schnittstellen deklariert werden. Diesen von der Programmiersprache bedingten Unterschieden folgend wurden die Schnittstellen aus dem C++ Teil der API angepasst, so dass alle Schnittstellen der C++ API, auch im.net Teil zu finden sind. Es soll im Folgenden nur auf einige der Schnittstellen eingegangen werden, weil sich die meisten nur wenig von ihrer C++ Variante unterscheiden Die Standardschnittstelle iplugin_base Die Schnittstelle iplugin_base spielt in der Plugin API für C++ eine besondere Rolle. Sie wird von allen Plugins genutzt und dient so als Basis für jeglichen Umgang mit einem Plugin. In.NET ist dies nicht mehr der Fall. Durch das wohldefinierten Typensystem von.net bedingt, erben alle Plugins von System.Object. Für eine Liste von Plugins, ist iplugin_base deshalb nicht mehr notwendig. Außerdem verliert die Methode create_new_instance in.net an Bedeutung, da hier die Plugins direkt aus den Pluginklassen erstellt werden. Somit enthält iplugin_base nur noch eine Methode um den Namen des Plugins zu ermitteln. Da die Schnittstelle in.net sehr verkleinert wurde und an Wichtigkeit verloren hat, muss sie auch nicht mehr von einem Plugin implementiert werden. Sie wurde aber trotzdem in die Plugin API für.net übernommen, weil es in vielen Fällen nützlich ist, einem Plugin einen Namen zuweisen zu können, um es dadurch leichter zu identifizieren Iplugin_event_callback Die Bezeichnung dieser Schnittstelle ist eigentlich nicht ganz korrekt. In.NET werden Rückruffunktionen als delegates bezeichnet. Da sie aber in ihrer Wirkungsweise den aus C++ bekannten callback Funktionen gleichen und damit die.net und die C++ Version der Plugin API möglichst einheitlich gestaltet sind, wurde der Name der C++ Schnittstelle übernommen. Da die Schnittstellen der.net Plugin API keine Implementationen besitzen, enthält iplugin_event_callback lediglich eine Deklaration der Eigenschaft set_event_callback. Diese Eigenschaft kann nur beschrieben aber nicht gelesen werden, d. h. sie bestitzt nur eine set Methode. Sie ist vom Typ plugin_event_delegate und soll in ihrer Implementation im Plugin, ein privaten delegate (Funktionszeiger) auf eine von der Hostanwendung bestimmte Funktion setzten. Das Plugin kann dann den Verweis auf die Funktion nutzen, um diese auszuführen. Eine so zugeordnete Funktion muss einen Parameter vom Aufzählungstyp enum_plugin_event haben. Dieser Typ beschreibt die Art des Ereignisses, welches das Plugin melden möchte.

32 4. DIE PLUGIN API FÜR.NET PluginLoader.NET Wie in C++, steht dem Entwickler einer Hostanwendung auch unter.net die Verwaltungsklasse plugin_loader zu Verfügung. Sie ist im Assembly PluginLoader definiert und enthält die gleichen Funktionen wie die Version der C++ Plugin API. Neue Plugin Assemblies können mit der überladenen Methode load geladen werden, wobei diese den Dateinamen des Assembly und optional eine Liste von Schnittstellen benötigt. Wird eine Liste übergeben, werden nur solche Plugins geladen, die alle Schnittstellen der Liste implementieren. Ist die Liste leer oder wird sie nicht übergeben, lädt die Verwaltungsklasse alle in der Bibliothek enthaltenen Plugins. Geladen wird ein Plugin durch die vom.net Framework bereitgestellten Klasse System.Reflection.Assembly. Die Verwaltungsklasse plugin_loader nutzt eine Instanz dieser Klasse, um mit Hilfe deren Memberfunktion LoadFrom das Assembly zu laden, welches durch den der Methode übergebenen Dateinamen spezifiziert wird. Eine weitere für das Laden von Plugins wichtige Funktion ist GetTypes. Sie ist ebenfalls Bestandteil der Assemblyklasse und liefert alle in einem Assembly enthaltenen Typen zurück. Ein plugin_loader Objekt nutzt die so erhaltenen Typen, um mit Hilfe Funktion CreateInstance des Assemblyobjektes, Instanzen von ihnen zu erstellen. Abbildung A.10 zeigt die load Funktion der plugin_loader Klasse. Der Zugriff auf die Plugins erfolgt analog zu C++, mit den Methoden get_plugin und get_interface. Auch in.net ist es möglich, einmal geladene Plugins, vor dem Programmende durch die Methode delete_plugin wieder zu entfernen. Im Unterschied zu C++, wird hier aber das Assembly nicht entladen, wenn kein in ihr enthaltenes Plugin mehr genutzt wird. Ein einmal dynamisch hinzugefügtes Assembly bleibt also bis zum Programmende der Hostanwendung geladen. Die Klasse plugin_loader nutzt eine Liste von Objekten zum speichern von Plugininstanzen. Diese ist wie in C++ vom Typ plugin_list, führt aber bisher keine eigenen Methoden ein.

33 5. BEISPIELANWENDUNGEN 31 5 Beispielanwendungen Neben der eigentlichen Plugin API, wurden im Rahmen dieses Belegs einige Beispielanwendungen erstellt. Diese sollen Einblicke in die Nutzung der API bringen und werden im Folgenden etwas genauer erklärt. 5.1 DirectX Beispiel für C++ Dieses Beispiel besteht aus einer Hostanwendung (SampleHost.exe) und zwei DLLs ( MeshDll.dll und InteractiveRoom.dll). Es nutzt die in der Direct X SDK (Software Development Kit) enthaltenen DXUT Hilfsklassen [11]. Abbildung 5.1: Screenshot aus der DirectX Beispielanwendung

34 5. BEISPIELANWENDUNGEN Die Hostanwendung Die Hostanwendung wird in der für DXUT typischen Weise initialisiert. Als Erstes werden den Ereignissen DeviceCreated, DeviceReset, DeviceLost, DeviceDestroyed, FrameRender und FrameMove Funktionen zur Behandlung des Ereignisses zugewiesen. Außerdem wird die Funktion zur Nachrichtenbehandlung der Anwendung festgelegt. Das Hauptfenster, die notwendigen DirectX Objekte werden durch DXUTInit, DXUTCreateWindow und DXUTCreateDevice erstellt. Danach wird die Hauptschleife in der Funktion DXUTMainLoop betreten. Neben dem plugin_loader Objekt werden eine Kamera (CModelViewerCamera) und ein Objekt für die grafische Benutzeroberfläche (SampleHostGUIClass) global definiert. Im Konstruktor der SampleHostGUIClass wird die Benutzeroberfläche erstellt. Zur Interaktion hält sie Knöpfe zum Laden und Entladen der Plugins bereit. In einer Liste werden alle geladenen Plugins angezeigt. Dafür wird der in der Schnittstelle iplugin_base definierte Name des Plugins genutzt. Um von der Hostanwendung geladen werden zu können, müssen die Plugins die Schnittstellen irenderable und id3d9_plugin implementieren. Ist ein Plugin in der Liste ausgewählt, dann wird dessen Memberfunktion render von der Hostanwendung aufgerufen. Im Falle eines Plugins dass ikeyboard_event_handler implementiert, werden zusätzlich die Tastendrücke der Hoch -Taste und Runter -Taste an das Plugin übergeben. Dies wird vom interaktives Auto Plugin in der Bibliothek InteractiveRoom.dll genutzt. Die Hostanwendung verwendet ein CModelViewerCamera Objekt, um eine vom Benutzer gesteuerte Kamera zu erzeugen. Der Nutzer der Anwendung kann so mit Hilfe der Maus die Position der Kamera verändern. Mit gedrückter Maustaste wird bei jeder Mausbewegung die Kamera Rotiert. Über das Mausrad kann ein Zoom ausgelöst werden Die Dll MeshDll Die Pluginbibliothek MeshDll enthält drei Plugins. Alle drei Plugins implementieren die Schnittstellen iplugin_base, irenderable und id3d9_plugin. Für jedes ist eine Fabrikklasse vohanden, von der das Plugin erbt. Da die Schnittstelle iplugin_base abstrakt ist, wird sie bereits in der Fabrik implementiert. Die Plugins nutzen den von der Hostanwendung erzeugten LPDIRECT3DDEVICE9 Zeiger um in der Funktion render Objekte grafisch auszugeben. Das Plugin TubeMeshPlugin zeichnet mit Hilfe eines Vertexbuffers eine Röhre. Das Plugin TeapotMeshPlugin lädt ein Teekannen-Objekt aus einer Datei und stellt es rotierend da. Beim Plugin TigerMeshPlugin wird ebenfalls ein Objekt aus einer Datei geladen und rotierend dargestellt. Der so gerenderte Tiger wird aber zusätzlich noch mit einer Textur versehen. Die DLL enthält weiterhin das zum Laden der Plugins notwendige plugin_factory_list_class Objekt. Diesem werden in DllMain Mittels register_factory die Plugins bekannt gemacht.

35 5. BEISPIELANWENDUNGEN Die DLL InteractiveRoom In der DLL InteractiveRoom ist ein Plugin enthalten. Dieses soll die Funktion der Schnittstelle ikeyboard_event_handler verdeutlichen. Es zeichnet ein Auto auf das gegebene IDIRECT3DDEVICE9 Objekt, welches sich je nach Tastendruck vorwärts oder rückwärts im Kreis bewegt. Genau wie bei der Pluginbibliothek MeshDll, ist auch hier für jedes Plugin eine Fabrik vorhanden, mit welcher das Plugin erzeugt werden kann. Das Plugin IACarPlugin nutzt sowohl ikeyboard_event_handler, als auch die für die Hostanwendung nötigen irenderable und id3d9_plugin. Die Schnittstelle iplugin_base wird, wie bei jedem Plugin, natürlich auch implementiert. 5.2 OpenGL Beispiel für C++ Dieses Beispiel besteht aus einer Hostanwendung (OGLHost.exe) und einer DLL ( OGLDll.dll). Zum erstellen wurde die Grafikbibliothek OpenGL und die Zusatzbibliothek GLUT verwendet. Abbildung 5.2: Screenshot aus der OpenGL Beispielanwendung

Beleg: API für Plugin und Treiberbasierte Softwareentwicklung

Beleg: API für Plugin und Treiberbasierte Softwareentwicklung Fakultät Informatik Institut für Software- und Multimediatechnik, Professur Computergraphik Beleg: API für Plugin und Treiberbasierte Dresden, 23. Mai 2007 Übersicht Grundlagen zum Plugin-Konzept Dynamische

Mehr

OOP. Kapselung: Gruppierung von Daten und Funktionen als Objekte. Definieren eine Schnittstelle zu diesen Objekten.

OOP. Kapselung: Gruppierung von Daten und Funktionen als Objekte. Definieren eine Schnittstelle zu diesen Objekten. Polymorphismus OOP Kapselung: Gruppierung von Daten und Funktionen als Objekte. Definieren eine Schnittstelle zu diesen Objekten. Vererbung: Erlaubt Code zwischen verwandten Typen wiederverwendet sein.

Mehr

Microsoft.NET Framework & Component Object Model. ein Vortrag von Florian Steuber

Microsoft.NET Framework & Component Object Model. ein Vortrag von Florian Steuber Microsoft.NET Framework & Component Object Model ein Vortrag von Florian Steuber Übersicht I..NET Framework 1. Was ist das.net Framework? 2. Das.NET Execution Model 3. Sprachunabhängigkeit, CTS und CLS

Mehr

Eine Kommando-Oberfläche für.net

Eine Kommando-Oberfläche für.net Institut für Systemsoftware O.Univ.-Prof. Dr. Hanspeter Mössenböck Eine Kommando-Oberfläche für.net In.NET (wie auch in vielen anderen Systemen) haben Programme nur einen einzigen Eintrittspunkt (ihre

Mehr

HSR Rapperswil 2001 Markus Rigling. Programmieren: Vererbung. 1 Variante 2

HSR Rapperswil 2001 Markus Rigling. Programmieren: Vererbung. 1 Variante 2 HSR Rapperswil 2001 Markus Rigling Programmieren: Vererbung 1 Variante 2 Inhaltsverzeichnis: 1. Was ist Vererbung...3 2. Anwendung...3 3. Realisierung...3 4. Vorgehensweise zur Erstellung einer Kind-Klasse...3

Mehr

Übungsblatt Programmierung und Software-Entwicklung Generizität, Interfaces, Listen, Sortieralgorithmen & JUnit

Übungsblatt Programmierung und Software-Entwicklung Generizität, Interfaces, Listen, Sortieralgorithmen & JUnit Übungsblatt Programmierung und Software-Entwicklung Generizität, Interfaces, Listen, Sortieralgorithmen & JUnit Aufgabe : Die allgemeine Object-Liste Gegeben sei folgendes UML-Klassendiagramm: MyObjectList

Mehr

Übung zur Vorlesung Wissenschaftliches Rechnen Sommersemester 2012 Auffrischung zur Programmierung in C++, 2. Teil

Übung zur Vorlesung Wissenschaftliches Rechnen Sommersemester 2012 Auffrischung zur Programmierung in C++, 2. Teil MÜNSTER Übung zur Vorlesung Wissenschaftliches Rechnen Sommersemester 2012 Auffrischung zur Programmierung in C++ 2. Teil 18. April 2012 Organisatorisches MÜNSTER Übung zur Vorlesung Wissenschaftliches

Mehr

Wie teuer ist dynamischer Polymorphismus? 194

Wie teuer ist dynamischer Polymorphismus? 194 Wie teuer ist dynamischer Polymorphismus? 194 Function f vtable data RTTI ~Function get_name type name type info "Sinus\0" execute Nicht-polymorphe Methoden und reguläre Funktionen können in C++ direkt

Mehr

Programmierung mit C Zeiger

Programmierung mit C Zeiger Programmierung mit C Zeiger Zeiger (Pointer)... ist eine Variable, die die Adresse eines Speicherbereichs enthält. Der Speicherbereich kann... kann den Wert einer Variablen enthalten oder... dynamisch

Mehr

Definitionen/Vorarbeit zum Thema Java

Definitionen/Vorarbeit zum Thema Java Definitionen/Vorarbeit zum Thema Java Programmiersprachen: System von Wörtern und Symbolen, die zur Formulierung von Programmen für die elektronische Datenverarbeitung verwendet werden. Arten: z.b. Javascript

Mehr

Janeva:.NET meets J2EE

Janeva:.NET meets J2EE Inhalt: Motivation Was ist Janeva? Systemvoraussetzungen Installation Beispiel Converter Fazit Motivation Motivation: Janeva testen einen Überblick verschaffen Lauffähiges Beispiel Entscheidungshilfe über

Mehr

Software Design basierend auf dem Plug-In Konzept

Software Design basierend auf dem Plug-In Konzept Software Design basierend auf dem Plug-In Konzept Michael Antes Seminar Simulation und Bildanalyse mit Java, WS2003 Universität Ulm Software-Design basierend auf dem Plug-In-Konzept Inhalt: Einführung:

Mehr

Einführung in C# Teil 1. Matthias Nübling

Einführung in C# Teil 1. Matthias Nübling Einführung in C# Teil 1 Matthias Nübling Vorausgesetzte Grundkenntnisse Programmierung Typen, Variablen, Anweisungen, Funktionen, etc. Objektorientierte Programmierung Klassen, Vererbung, Polymorphismus,

Mehr

Seminar Softwarearchitekturen SoSe Martin Schrage

Seminar Softwarearchitekturen SoSe Martin Schrage Seminar Softwarearchitekturen SoSe 2011 Martin Schrage Gliederung 1. Common Language Infrastructur 2. Microsoft.NET 2.1Common Language Runtime 2.2 Programmausführung 2.3 Framework Class Library 2.4 Programmiersprachen

Mehr

9.5 Microsoft.NET

9.5 Microsoft.NET 9.5 Microsoft.NET http://www.microsoft.com/net http://msdn.microsoft.com/netframework Architektur: objektorientiert/fernaufrufe (8.1.6 ) IDL: (unsichtbare Metadaten, vom Übersetzer erzeugt) Dienste: (über

Mehr

Objekte. Theorieteil. Inhaltsverzeichnis. Begriffe. Programmieren mit Java Modul 5. 1 Modulübersicht 3

Objekte. Theorieteil. Inhaltsverzeichnis. Begriffe. Programmieren mit Java Modul 5. 1 Modulübersicht 3 Programmieren mit Java Modul 5 Objekte Theorieteil Inhaltsverzeichnis 1 Modulübersicht 3 2 Klassen und Objekte 3 2.1 Klassen.................................... 4 2.2 Objektvariablen und Methoden.......................

Mehr

Das Interface-Konzept am Beispiel der Sprache Java

Das Interface-Konzept am Beispiel der Sprache Java Das Interface-Konzept am Beispiel der Sprache Java Klaus Kusche, November 2013 Inhalt Motivation: Wozu braucht man Interfaces? Interfaces in Java Was spricht gegen die große Lösung? Voraussetzungen Kenntnisse

Mehr

3 VERERBUNG ALLGEMEINES

3 VERERBUNG ALLGEMEINES 3 VERERBUNG ALLGEMEINES Leitideen: Die Hinzufügung von Daten- oder Funktionskomponenten zu einer vorhandenen Klasse (Basisklasse) wird als Vererbung und die auf diese Weise erzeugte Klasse als abgeleitete

Mehr

Konzepte von Betriebssystem-Komponenten. Programmstart & dynamische Bibliotheken SS 05. Wladislaw Eckhardt.

Konzepte von Betriebssystem-Komponenten. Programmstart & dynamische Bibliotheken SS 05. Wladislaw Eckhardt. Proseminar KVBK Programmstart dynamische Bibliotheken Konzepte von Betriebssystem-Komponenten Programmstart & dynamische Bibliotheken SS 05 Wladislaw Eckhardt Wladi23@gmx.net 1 1 Einleitung 1.1 Problematik

Mehr

C++ - Einführung in die Programmiersprache Header-Dateien und Funktionen. Leibniz Universität IT Services Anja Aue

C++ - Einführung in die Programmiersprache Header-Dateien und Funktionen. Leibniz Universität IT Services Anja Aue C++ - Einführung in die Programmiersprache Header-Dateien und Funktionen Leibniz Universität IT Services Anja Aue Modularisierung Logische Gliederung von Programmteilen mit Hilfe von Namensräumen. Aufteilung

Mehr

Einstieg in die Informatik mit Java

Einstieg in die Informatik mit Java 1 / 35 Einstieg in die Informatik mit Java Vererbung Gerd Bohlender Institut für Angewandte und Numerische Mathematik Gliederung 2 / 35 1 Grundlagen 2 Verdeckte Variablen 3 Verdeckte Methoden 4 Konstruktoren

Mehr

Objektorientierte Programmierung. Agenda für heute, 26. März, Eines der drei wichtigsten Programmierparadigmen

Objektorientierte Programmierung. Agenda für heute, 26. März, Eines der drei wichtigsten Programmierparadigmen Agenda für heute, 26. März, 2009 Imperatives vs. objektorientiertes Programmieren Lesen Sie den Begleittext Seite 79 85 Eines der drei wichtigsten Programmierparadigmen (Paradigma: Denkmuster) Imperative

Mehr

2.1 Visual C Express installieren Visual C Express starten Visual C Express registrieren...

2.1 Visual C Express installieren Visual C Express starten Visual C Express registrieren... Datei: 5220_A02Inhalt.doc, Seite3 15. September 2010 Teil I Erste Schritte 1 Einleitung.... 9 1.1 Was Sie erwartet und was Sie nicht erwartet.... 9 1.2 Wie die Kapitel aufgebaut sind.... 10 1.3 Beispieldateien....

Mehr

Schlussendlich geben wir die Listen aus. Es kommt zu folgender Ausgabe:

Schlussendlich geben wir die Listen aus. Es kommt zu folgender Ausgabe: Musterlösung Übung 7 Aufgabe 1 Sehen wir uns zu allererst das gegebene Forth Programm an: 0 3 new - list constant list1 list1 5 new - list constant list2 list1 6 new - list constant list3 list2 2 new -

Mehr

Programmieren in Java -Eingangstest-

Programmieren in Java -Eingangstest- Programmieren in Java -Eingangstest- Nummer: 1. Studiengang: Informatik B.Sc. Informatik M.Sc. ESE B.Sc. ESE M.Sc. Sonstiges: Fachsemester: Bitte Fragen, die Sie nicht beantworten können unbedingt mit

Mehr

Klassen als Objekte. Smalltalk vs. Objective-C. Self-Nachrichten an Klassen in Objective-C. Klassen als Objekte. Smalltalk: Everything is an object

Klassen als Objekte. Smalltalk vs. Objective-C. Self-Nachrichten an Klassen in Objective-C. Klassen als Objekte. Smalltalk: Everything is an object Smalltalk vs. Objective-C Klassen als Objekte Klassendeklarationen Selektoren als first-class values Objekt-Erzeugung Implementierung: Eigene VM vs. Einbettung in C Smalltalk: Everything is an object Klassen

Mehr

- dynamisches Laden -

- dynamisches Laden - - - Fachbereich Technik Department Elektrotechnik und Informatik 21. Juni 2012 1/23 2/23 s dynamisch Code kann von mehreren Programmen genutzt werden => kleinere Programme einzelne Teile eines Programms

Mehr

Handbuch für die Erweiterbarkeit

Handbuch für die Erweiterbarkeit Handbuch für die Erweiterbarkeit Inhalt Pakete für die Erweiterbarkeit... 2 Actions... 2 Items... 2 Itemset... 2 Die UseCaseNewAction... 3 Eigene Shapes... 4 Der Shape Container... 5 User Objects... 6

Mehr

Kapitel 1: Die ersten Schritte 1

Kapitel 1: Die ersten Schritte 1 Kapitel 1: Die ersten Schritte Thema: Programmieren Seite: 1 Kapitel 1: Die ersten Schritte 1 Starten Sie Eclipse. Importieren Sie das Eclipse-Projekt scenarios-chapter-1. Gehen Sie in den Unterordner

Mehr

Einführung: Verteilte Systeme - Remote Method Invocation -

Einführung: Verteilte Systeme - Remote Method Invocation - Einführung: Verteilte Systeme - - Prof. Dr. Michael Cebulla 11. Dezember 2014 Fachhochschule Schmalkalden Wintersemester 2014/15 1 / 43 M. Cebulla Verteilte Systeme Gliederung 1 2 Architektur RMI Kommunikation

Mehr

Objektorientierte Programmierung (OOP)

Objektorientierte Programmierung (OOP) orientierte Programmierung (OOP) 1. Motivation Die objektorientierte Sichtweise der Welt Als Motivation für die OOP sieht man sich am besten die reale Welt an: Die reale Welt besteht aus "en", z. B.: Gegenstände,

Mehr

6. Zeiger Allgemeines Definition eines Zeigers

6. Zeiger Allgemeines Definition eines Zeigers 6. Zeiger www.c-programme.de Stefan Thiemert Kapitel 6 - Seite 1 von 6 6. 1. Allgemeines Zeiger spielen in der Programmierung eine wichtige Rolle. Sie sind wichtig, bei der Arbeit mit Arrays und Funktionen.

Mehr

Java: Kapitel 1. Überblick. Programmentwicklung WS 2008/2009. Holger Röder Holger Röder

Java: Kapitel 1. Überblick. Programmentwicklung WS 2008/2009. Holger Röder Holger Röder Java: Kapitel 1 Überblick Programmentwicklung WS 2008/2009 Holger Röder holger.roeder@informatik.uni-stuttgart.de Was ist Java? Die Java-Technologie umfasst die Programmiersprache Java sowie die Java-Plattform

Mehr

Einstieg in die Informatik mit Java

Einstieg in die Informatik mit Java 1 / 41 Einstieg in die Informatik mit Java Vererbung Gerd Bohlender Institut für Angewandte und Numerische Mathematik Gliederung 2 / 41 1 Überblick: Vererbung 2 Grundidee Vererbung 3 Verdeckte Variablen

Mehr

Auf dieser und den beiden folgenden Folien wurde jeweils ein neues Objekt der Klasse FigurMalerei erstellt und die angegebene Methode ausgeführt.

Auf dieser und den beiden folgenden Folien wurde jeweils ein neues Objekt der Klasse FigurMalerei erstellt und die angegebene Methode ausgeführt. 432 433 434 435 Auf dieser und den beiden folgenden Folien wurde jeweils ein neues Objekt der Klasse FigurMalerei erstellt und die angegebene Methode ausgeführt. 436 437 438 439 440 441 442 443 Die verkürzte

Mehr

Kapitel 21 Nativer Code

Kapitel 21 Nativer Code Kapitel 21 Nativer Ali Jannessari IPD Tichy Lehrstuhl für Programmiersysteme KIT die Kooperation von Forschungszentrum Karlsruhe GmbH und Universität Karlsruhe (TH) Wann muss man verwalteten und nicht-verwalteten

Mehr

C++ - Objektorientierte Programmierung Konstante und statische Elemente

C++ - Objektorientierte Programmierung Konstante und statische Elemente C++ - Objektorientierte Programmierung Konstante und statische Elemente hat eine Kantenlänge hat eine Füllfarbe Kantenlänge setzen Füllfarbe lesen Volumen berechnen Leibniz Universität IT Services Anja

Mehr

OpenCL. Programmiersprachen im Multicore-Zeitalter. Tim Wiersdörfer

OpenCL. Programmiersprachen im Multicore-Zeitalter. Tim Wiersdörfer OpenCL Programmiersprachen im Multicore-Zeitalter Tim Wiersdörfer Inhaltsverzeichnis 1. Was ist OpenCL 2. Entwicklung von OpenCL 3. OpenCL Modelle 1. Plattform-Modell 2. Ausführungs-Modell 3. Speicher-Modell

Mehr

C++ - Objektorientierte Programmierung Konstruktoren und Destruktoren

C++ - Objektorientierte Programmierung Konstruktoren und Destruktoren C++ - Objektorientierte Programmierung Konstruktoren und Destruktoren hat eine Kantenlänge hat eine Füllfarbe Kantenlänge setzen Füllfarbe lesen Volumen berechnen Leibniz Universität IT Services Anja Aue

Mehr

Objektorientierte Programmierung. Kapitel 22: Aufzählungstypen (Enumeration Types)

Objektorientierte Programmierung. Kapitel 22: Aufzählungstypen (Enumeration Types) Stefan Brass: OOP (Java), 22. Aufzählungstypen 1/20 Objektorientierte Programmierung Kapitel 22: Aufzählungstypen (Enumeration Types) Stefan Brass Martin-Luther-Universität Halle-Wittenberg Wintersemester

Mehr

Ein erstes "Hello world!" Programm

Ein erstes Hello world! Programm OOP Henrik Horstmann 14. September 2014 Inhaltsverzeichnis Inhaltsverzeichnis 1 Bedeutung der Symbole...1 2 Die Benutzer Oberfläche von HOOPLU...2 2.1 Projekte öffnen und speichern...2 2.2 Die Klasse Program

Mehr

Objektorientierte Programmierung. Agenda für heute, 1. April, Eines der drei wichtigsten Programmierparadigmen

Objektorientierte Programmierung. Agenda für heute, 1. April, Eines der drei wichtigsten Programmierparadigmen Agenda für heute, 1. April, 2010 Imperatives vs. objektorientiertes Programmieren Lesen Sie den Begleittext Seite 79 85 Eines der drei wichtigsten Programmierparadigmen (Paradigma: Denkmuster) Imperative

Mehr

Mapra: C++ Teil 6. Felix Gruber, Sven Groß. IGPM, RWTH Aachen. 13. Juni 2017

Mapra: C++ Teil 6. Felix Gruber, Sven Groß. IGPM, RWTH Aachen. 13. Juni 2017 Mapra: C++ Teil 6 Felix Gruber, Sven Groß IGPM, RWTH Aachen 13. Juni 2017 Felix Gruber, Sven Groß (IGPM, RWTH Aachen) Mapra: C++ Teil 6 13. Juni 2017 1 / 22 Was bisher geschah Klassen I Attribute und Methoden

Mehr

Universität Stuttgart Institut für Automatisierungstechnik und Softwaresysteme Prof. Dr.-Ing. M. Weyrich

Universität Stuttgart Institut für Automatisierungstechnik und Softwaresysteme Prof. Dr.-Ing. M. Weyrich Universität Stuttgart Institut für Automatisierungstechnik und Softwaresysteme Prof. Dr.-Ing. M. Weyrich WS 02/03 Warum muss ein Objekt wissen, zu welcher Klasse es gehört? Damit die Klassenzugehörigkeit

Mehr

Objektorientierte Programmierung II

Objektorientierte Programmierung II Objektorientierte Programmierung II OOP I Erlaubt Entwicklers, im Problemraum zu denken und zu arbeiten. Das Problem wird in eine Menge von Objekten zerlegt. Objekte wirken aufeinander, um das Problem

Mehr

HYDROINFORMATIK. Integrated development environments IDEs. JProf. Dr. rer. nat. Marc Walther

HYDROINFORMATIK. Integrated development environments IDEs. JProf. Dr. rer. nat. Marc Walther HYDROINFORMATIK Integrated development environments IDEs JProf. Dr. rer. nat. Marc Walther Dresden, 20. Oktober 2017 LETZTES MAL Einführung in Veranstaltung, Organisatorisches Überblick Anwendungen HI

Mehr

C++ - Objektorientierte Programmierung Polymorphie

C++ - Objektorientierte Programmierung Polymorphie C++ - Objektorientierte Programmierung Polymorphie hat eine Kantenlänge hat eine Füllfarbe Kantenlänge setzen Füllfarbe lesen Volumen berechnen C++ - Objektorientierte Programmierung 21.06.16 Seite 1 Polymorphie

Mehr

DAP2-Programmierpraktikum Einführung in C++ (Teil 2)

DAP2-Programmierpraktikum Einführung in C++ (Teil 2) DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 Algorithm Engineering Fakultät für Informatik, TU Dortmund Überblick Dynamischer Speicher Klassen und

Mehr

Methoden und Wrapperklassen

Methoden und Wrapperklassen Methoden und Wrapperklassen CoMa-Übung IV TU Berlin 06.11.2012 CoMa-Übung IV (TU Berlin) Methoden und Wrapperklassen 06.11.2012 1 / 24 Themen der Übung 1 Methoden 2 Wrapper-Klassen CoMa-Übung IV (TU Berlin)

Mehr

Anwendungsentwicklung mit Java. Grundlagen der OOP, Vererbung, Schnittstellen, Polymorphie

Anwendungsentwicklung mit Java. Grundlagen der OOP, Vererbung, Schnittstellen, Polymorphie Anwendungsentwicklung mit Java Grundlagen der OOP, Vererbung, Schnittstellen, Polymorphie Vererbung (1) 2 Problem: Objekte mit gleichen Attributen/Methoden, aber nicht völlig identisch, z.b., LKW, PKW,

Mehr

Kapitel 02. Java was, wann, warum, wieso. Fachgebiet Knowledge Engineering Prof. Dr. Johannes Fürnkranz

Kapitel 02. Java was, wann, warum, wieso. Fachgebiet Knowledge Engineering Prof. Dr. Johannes Fürnkranz Kapitel 02 Java was, wann, warum, wieso Java, eine objektorientierte Programmiersprache Java ist eine objektorientierte Programmiersprache und als solche ein eingetragenes Warenzeichen der Firma Sun Microsystems.

Mehr

Inhaltsverzeichnis. Grundlagen und Einführung (1. Band) 1

Inhaltsverzeichnis. Grundlagen und Einführung (1. Band) 1 Inhaltsverzeichnis Grundlagen und Einführung (1. Band) 1 1 Einleitung und Vorwort 1 1.1 Vorwort zur 13. Auflage....................... 1 1.2 Vorwort zur 10. Auflage....................... 1 1.3 Voraussetzungen...........................

Mehr

Programmieren II. Dr. Klaus Höppner. Hochschule Darmstadt WS 2006/2007

Programmieren II. Dr. Klaus Höppner. Hochschule Darmstadt WS 2006/2007 Programmieren II Dr. Klaus Höppner Hochschule Darmstadt WS 2006/2007 1 / 15 Einführung: Grafische Benutzeroberflächen 2 / 15 Einführung: GUI Fast alle Programme besitzen mittlerweile eine grafische Benutzeroberfläche

Mehr

Vererbung. Gerd Bohlender. Institut für Angewandte und Numerische Mathematik. Vorlesung: Einstieg in die Informatik mit Java 23.5.

Vererbung. Gerd Bohlender. Institut für Angewandte und Numerische Mathematik. Vorlesung: Einstieg in die Informatik mit Java 23.5. Vererbung Gerd Bohlender Institut für Angewandte und Numerische Mathematik Vorlesung: Einstieg in die Informatik mit Java 23.5.07 G. Bohlender (IANM UNI Karlsruhe) Vererbung 23.5.07 1 / 22 Übersicht 1

Mehr

Hello World! Eine Einführung in das Programmieren Das erste Programm

Hello World! Eine Einführung in das Programmieren Das erste Programm Hello World! Eine Einführung in das Programmieren Das erste Programm Görschwin Fey Institute of Embedded Systems Hamburg University of Technology Slide 2 Betriebssystem Funktion Anwendung Gerätesteuerung

Mehr

Konzepte von Betriebssystem-Komponenten. Programmstart & dynamische Bibliotheken SS 05. Wladislaw Eckhardt.

Konzepte von Betriebssystem-Komponenten. Programmstart & dynamische Bibliotheken SS 05. Wladislaw Eckhardt. Proseminar KVBK Programmstart dynamische Bibliotheken Konzepte von Betriebssystem-Komponenten Programmstart & dynamische Bibliotheken SS 05 Wladislaw Eckhardt Wladi23@gmx.net 1 1 Einleitung 11. Problematik

Mehr

Unterprogramme. AnPr. Wiederholungen im Code werden vermieden. Programme werden leichter lesbar. Die Entwicklung und der Test werden vereinfacht.

Unterprogramme. AnPr. Wiederholungen im Code werden vermieden. Programme werden leichter lesbar. Die Entwicklung und der Test werden vereinfacht. Name Klasse Datum 1 Allgemeines Programme werden üblicherweise nicht als ein einziger, fortlaufender Programmcode verfasst, sondern mit geeigneten Mitteln unterteilt und somit strukturiert. Die Methodik

Mehr

Grundlagen der OO- Programmierung in C#

Grundlagen der OO- Programmierung in C# Grundlagen der OO- Programmierung in C# Technische Grundlagen 1 Dr. Beatrice Amrhein Überblick Visual Studio: Editor und Debugging Die Datentypen Methoden in C# Die Speicherverwaltung 2 Visual Studio 3

Mehr

Languages and Tools for Object-Oriented Development Klausur Wintersemester 2007/2008

Languages and Tools for Object-Oriented Development Klausur Wintersemester 2007/2008 Languages and Tools for Object-Oriented Development Klausur Wintersemester 2007/2008 27. Februar 2008 Institut für Softwaresysteme, TUHH Regeln: 1. Zu dieser Klausur sind keinerlei Hilfsmittel zugelassen.

Mehr

Von der UML nach C++

Von der UML nach C++ 22 Von der UML nach C++ Dieses Kapitel behandelt die folgenden Themen: Vererbung Interfaces Assoziationen Multiplizität Aggregation Komposition Die Unified Modeling Language (UML) ist eine weit verbreitete

Mehr

Grundlagen der Informatik

Grundlagen der Informatik Grundlagen der Informatik Polymorphie, Abstrakte Klassen, Mehrfachvererbung Prof. Dr.-Ing. Thomas Wiedemann Prof. Dr. rer.nat. Ralph Großmann Fachgebiet Informatik / Mathematik Überblick zum Inhalt Klassen-3

Mehr

Einleitung Typsystem Typisierung Zusammenfassung Literatur. Typisierung. Effiziente Programmierung. Thomas Schnieders

Einleitung Typsystem Typisierung Zusammenfassung Literatur. Typisierung. Effiziente Programmierung. Thomas Schnieders Typisierung Effiziente Programmierung Thomas Schnieders Fachbereich Informatik Fakultät für Mathematik, Informatik und Naturwissenschaften Universität Hamburg 2018-04-26 Thomas Schnieders Typisierung 1

Mehr

Programmieren in Java

Programmieren in Java Einführung in die Objektorientierung Teil 4 Interfaces, innere Klassen und Polymorphie 2 Vererbung im Klassendiagram (Wiederholung) Vererbung repräsentiert eine ist ein Beziehung zwischen Klassen Ware

Mehr

6 ZEIGER UND REFERENZEN - ALLGEMEINES

6 ZEIGER UND REFERENZEN - ALLGEMEINES 6 ZEIGER UND REFERENZEN - ALLGEMEINES Leitideen: Zeiger sind Adressen mit zusätzlicher Typinformation über das dort gespeicherte Objekt. Die Vereinbarungssyntax soll der Ausdruckssyntax entsprechen und

Mehr

Objektorientiertes Programmieren in C++

Objektorientiertes Programmieren in C++ Nicolai Josuttis Objektorientiertes Programmieren in C++ Von der Klasse zur Klassenbibliothek D-64289 Darmstadt ADDISON-WESLEY PUBLISHING COMPANY Bonn Paris Reading, Massachusetts Menlo Park, California

Mehr

Mathematik Seminar WS 2003: Simulation und Bildanalyse mit Java. Software-Architektur basierend auf dem Plug-in-Konzept

Mathematik Seminar WS 2003: Simulation und Bildanalyse mit Java. Software-Architektur basierend auf dem Plug-in-Konzept Mathematik Seminar WS 2003: Simulation und Bildanalyse mit Java Software-Architektur basierend auf dem Plug-in-Konzept Aufteilung: Probleme mit normaler/alter Software Ziele des Software Engineerings Die

Mehr

HYDROINFORMATIK. Integrated development environment IDEs. JProf. Dr. rer. nat. Marc Walther

HYDROINFORMATIK. Integrated development environment IDEs. JProf. Dr. rer. nat. Marc Walther HYDROINFORMATIK Integrated development environment IDEs JProf. Dr. rer. nat. Marc Walther Dresden, 21. Oktober 2016 LETZTES MAL Einführung in Veranstaltung, Organisatorisches Überblick Anwendungen HI 21.10.2016

Mehr

Vererbung, Polymorphie

Vererbung, Polymorphie Vererbung, Polymorphie Gerd Bohlender Institut für Angewandte und Numerische Mathematik Vorlesung: Einstieg in die Informatik mit Java 21.1.08 G. Bohlender (IANM UNI Karlsruhe) Vererbung, Polymorphie 21.1.08

Mehr

Maschinencode Dateiformat und Stackframes

Maschinencode Dateiformat und Stackframes Maschinencode Dateiformat und Stackframes Proseminar C-Programmierung - Grundlagen und Konzepte Julian M. Kunkel julian.martin.kunkel@informatik.uni-hamburg.de Wissenschaftliches Rechnen Fachbereich Informatik

Mehr

Algorithmen und Datenstrukturen Sommersemester Übung Abgabe bis , 10:00 Uhr

Algorithmen und Datenstrukturen Sommersemester Übung Abgabe bis , 10:00 Uhr 4. Übung Abgabe bis 24.05.2010, 10:00 Uhr Aufgabe 4.1: Referenzen Geben Sie Ihre Lösung als Referenzen.pdf ab. 16 Punkte a) Führen Sie einen Schreibtischlauf des folgenden Java-Programms durch. Es werden

Mehr

Typsystem Plattform- und Sprachenunabhängigkeit in.net

Typsystem Plattform- und Sprachenunabhängigkeit in.net Typsystem Plattform- und Sprachenunabhängigkeit in.net C# J# VB.NET Zwischencode CIL Windows Unix Auf welchen Grundlagen basiert dies? Komponenten & Frameworks Seite 1 Typsystem Grundlagen - CLR Common

Mehr

C++ - Einführung in die Programmiersprache Zeiger, Referenzen und Strukturen. Leibniz Universität IT Services Anja Aue

C++ - Einführung in die Programmiersprache Zeiger, Referenzen und Strukturen. Leibniz Universität IT Services Anja Aue C++ - Einführung in die Programmiersprache Zeiger, Referenzen und Strukturen Leibniz Universität IT Services Anja Aue Zeiger (Pointer) Verweis auf eine Speicherstelle. Speicherung einer Speicheradresse.

Mehr

C-Programme kompilieren mit Visual Studio Express

C-Programme kompilieren mit Visual Studio Express C-Programme kompilieren mit Visual Studio Express Die Beispiele, Aufgaben und Lösungen zum Buch C als erste Programmiersprache können mit Visual Studio Express von Microsoft bearbeitet, kompiliert und

Mehr

Einfache Liste: Ein Stapel (Stack) Ansatz. Schaubild. Vorlesung 1. Handout S. 2. Die einfachste Form einer Liste ist ein Stapel (stack).

Einfache Liste: Ein Stapel (Stack) Ansatz. Schaubild. Vorlesung 1. Handout S. 2. Die einfachste Form einer Liste ist ein Stapel (stack). Programmieren I Martin Schultheiß Hochschule Darmstadt Sommersemester 2011 1 / 64 2 / 64 Motivation Hauptteil dieser Vorlesung sind die so genannten. Zur Motivation (und als Vorbereitung der Datencontainer-Klassen

Mehr

Vorlesung Datenstrukturen

Vorlesung Datenstrukturen Vorlesung Datenstrukturen Objektorientierung in C++ (3) Aspekte der Vererbung (1) Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 546 Zuweisung bei Vererbung Dr. Frank Seifert Vorlesung

Mehr

OOP und Angewandte Mathematik. Eine Einführung in die Anwendung objektorientierter Konzepte in der angewandten Mathematik

OOP und Angewandte Mathematik. Eine Einführung in die Anwendung objektorientierter Konzepte in der angewandten Mathematik Eine Einführung in die Anwendung objektorientierter Konzepte in der angewandten Mathematik WS 2011/12 Inhalt Test-Besprechung! Ziele verdeutlichen Große Bild von OOP Wiederholung: Einbettung als Technik

Mehr

Übungsserie Nr. 6. Ausgabe: 1. April 2015 Abgabe: 15. April Hinweise

Übungsserie Nr. 6. Ausgabe: 1. April 2015 Abgabe: 15. April Hinweise Informatik II (D-ITET) Frühjahrssemester 2015 Prof. Friedemann Mattern Christian Beckel (beckel@inf.ethz.ch) ETH Zürich Institut für Pervasive Computing Gruppe für Verteilte Systeme http://vs.inf.ethz.ch

Mehr

Organisatorisches. Folien (u.a.) gibt's auf der Lva-Homepage zum Download

Organisatorisches. Folien (u.a.) gibt's auf der Lva-Homepage zum Download Organisatorisches Folien (u.a.) gibt's auf der Lva-Homepage zum Download Diesen Mi erstes Tutorium (15-17) Ab nächster Woche montags 10-12 (jeweils im Computerraum) 17.10.2017 IT I - VO 3 1 Organisatorisches

Mehr

Präsentation Interfaces

Präsentation Interfaces Einführung in Java Präsentation Interfaces Nozar Delassaei Marvi Inhalt 1. Erinnerung Klasse Objekte Beispiel Klasse Abstrakte Klasse Beispiel Abstrakte Klasse Mehrfachvererbung-1 Mehrfachvererbung-2 2.

Mehr

Einführung in die Programmierung 1

Einführung in die Programmierung 1 Einführung in die Programmierung 1 Einführung (S.2) Einrichten von Eclipse (S.4) Mein Erstes Programm (S.5) Hallo Welt!? Programm Der Mensch (S.11) Klassen (S.12) Einführung Wie Funktioniert Code? Geschriebener

Mehr

Client/Server-Programmierung

Client/Server-Programmierung Client/Server-Programmierung WS 2017/2018 Betriebssysteme / verteilte Systeme rolanda.dwismuellera@duni-siegena.de Tel.: 0271/740-4050, Büro: H-B 8404 Stand: 12. Januar 2018 Betriebssysteme / verteilte

Mehr

Einstieg in die Informatik mit Java

Einstieg in die Informatik mit Java 1 / 16 Einstieg in die Informatik mit Java Innere Klassen Gerd Bohlender Institut für Angewandte und Numerische Mathematik Gliederung 2 / 16 1 Einführung 2 Element-Klassen 3 Lokale Klassen 4 Anonyme Klassen

Mehr

Polymorphie und UML Klassendiagramme

Polymorphie und UML Klassendiagramme Polymorphie und UML Klassendiagramme Prof. Dr.-Ing. Thomas Schwotzer 1 Einführung Vererbung hat einen sehr interessanten und effektiven Effekt: die Polymorphie. Darum geht es in dieser Veranstaltung. 2

Mehr

Konzepte von Betriebssystemkomponenten

Konzepte von Betriebssystemkomponenten Konzepte von Betriebssystemkomponenten Systemstart und Programmausführung Seminarvortrag 15.12.2003, Michael Moese Übersicht 2. Systemstart 3. Programmausführung TEIL 1: Systemstart 1.1 Das BIOS 1.2 Der

Mehr

Objektorientierte Programmierung mite**

Objektorientierte Programmierung mite** mc Jürgen Franz/Christoph Mattheis Objektorientierte Programmierung mite** Systemunabhängig umsteigen auf C ++ Windowsprogrammierung Beispiele für UNIX Mit 66 Abbildungen Franzis 9 Inhalt 1 Überblick C++

Mehr

Organisatorisches. Folien (u.a.) auf der Lva-Homepage Skriptum über MU Online

Organisatorisches. Folien (u.a.) auf der Lva-Homepage Skriptum über MU Online Organisatorisches Folien (u.a.) auf der Lva-Homepage Skriptum über MU Online Nächste Woche VO und UE am Dienstag, den 30.10.! UE im CR IL/IT Wissensüberprüfung am Zettel 25.10.2018 IT I - VO 3 1 Organisatorisches

Mehr

1 Klassen und Objekte

1 Klassen und Objekte 1 Klassen und Objekte Datentyp - Spezifikation des Typs von Datenobjekten Datenstruktur - logische Ordnung von Elementen eines Datentyps - zur (effizienten) Speicherung, Verwaltung, Zugriff - auf die Elemente

Mehr

Modul Entscheidungsunterstützung in der Logistik. Einführung in die Programmierung mit C++ Übung 4

Modul Entscheidungsunterstützung in der Logistik. Einführung in die Programmierung mit C++ Übung 4 Fakultät Verkehrswissenschaften Friedrich List, Professur für Verkehrsbetriebslehre und Logistik Modul Entscheidungsunterstützung in der Logistik Einführung in die Programmierung mit C++ Übung 4 SS 2016

Mehr

Programmieren in C/C++ und MATLAB

Programmieren in C/C++ und MATLAB Programmieren in C/C++ und MATLAB Christian-Albrechts-Universität zu Kiel CAU 8-1 Objektorientiertes Programmieren Die Programme, die bisher in diesem Kurs verwendet wurden, sind alle klein und überschaubar

Mehr

3 Properties, Bindings und JavaFX-Collections

3 Properties, Bindings und JavaFX-Collections Properties, Bindings und JavaFX Collections 31 3 Properties, Bindings und JavaFX-Collections Dieses Kapitel beschäftigt sich mit wichtigem Basiswissen für das Verständnis der JavaFX Elemente. Nachdem wieder

Mehr

Einführung in die Programmierung I. 11. Vererbung. Stefan Zimmer

Einführung in die Programmierung I. 11. Vererbung. Stefan Zimmer Einführung in die Programmierung I 11. Vererbung Stefan Zimmer 21.1.2008 Programmcode wiederverwenden Wenn wir einige Klassen geschrieben haben, werden wir dabei Teile davon öfters hingeschrieben haben

Mehr

Prof. W. Henrich Seite 1

Prof. W. Henrich Seite 1 Klasse - ist ein benutzerdefinierter Datentyp (Referenztyp) - hat Datenelemente - hat Methoden - Konstruktor ist spezielle Methode zum Erstellen eines Objektes vom Typ der Klasse (Instanz) - jede Klasse

Mehr

Benutzerhandbuch Koala Editor

Benutzerhandbuch Koala Editor Benutzerhandbuch Koala Editor Inhalt Einführung, Allgemeine Hinweise... 2 Installation... 2 Allgemeine Funktionen... 3 Neu... 3 Öffnen und Speichern... 4 Modulfunktionen... 5 Klassisches Zustandsdiagramm...

Mehr

Computeranwendung in der Chemie Informatik für Chemiker(innen) 3. Software

Computeranwendung in der Chemie Informatik für Chemiker(innen) 3. Software Computeranwendung in der Chemie Informatik für Chemiker(innen) 3. Software Jens Döbler 2003 "Computer in der Chemie", WS 2003-04, Humboldt-Universität VL3 Folie 1 Grundlagen Software steuert Computersysteme

Mehr

Medienproduktion Sommersemester Dipl.-Inform. Alexander Schulze Prof. Dr. Ing. Klaus Rebensburg

Medienproduktion Sommersemester Dipl.-Inform. Alexander Schulze Prof. Dr. Ing. Klaus Rebensburg Medienproduktion Sommersemester 2010 Dipl.-Inform. Alexander Schulze Prof. Dr. Ing. Klaus Rebensburg Ablauf Heute Fortsetzung Programmierung mit Flash objektorientierte Programmierung - Dokumentklassen

Mehr

Kapitel 9. Programmierkurs. Attribute von Klassen, Methoden und Variablen. 9.1 Attribute von Klassen, Methoden und Variablen

Kapitel 9. Programmierkurs. Attribute von Klassen, Methoden und Variablen. 9.1 Attribute von Klassen, Methoden und Variablen Kapitel 9 Programmierkurs Birgit Engels Anna Schulze Zentrum für Angewandte Informatik Köln Objektorientierte Programmierung Attribute von Klassen, Methoden und Variablen Interfaces WS 07/08 1/ 18 2/ 18

Mehr

Grundlagen. Felix Döring, Felix Wittwer 24. April Python-Kurs

Grundlagen. Felix Döring, Felix Wittwer 24. April Python-Kurs Grundlagen Felix Döring, Felix Wittwer 24. April 2017 Python-Kurs Gliederung 1. Scriptcharakter 2. Programmierparadigmen Imperatives Programmieren Das Scoping Problem Objektorientiertes Programmieren 3.

Mehr

Programmieren in Java

Programmieren in Java Einführung in die Objektorientierung Teil 4 Interfaces, Polymorphie und innere Klassen 2 Vererbung im Klassendiagramm (Wiederholung) Vererbung repräsentiert eine ist ein Beziehung zwischen Klassen Object

Mehr