Generi-C ist eine Fortentwicklung der überaus erfolgreichen und gerade im Bereich der Embedded Software nach wie vor sehr beliebten Programmiersprache C, die behutsam um einige zentrale Elemente zur Optimierung der Wiederverwendbarkeit von Softwareteilen erweitert wurde. Unseres Wissens ist Generi-C die erste Programmiersprache, die gleichzeitig folgende Wiederverwendungstechniken unterstützt:
- Generische Programmierung: die in Generi-C analog zu Modulen in C programmierten Einheiten sind immer automatisch und ohne weitere Arbeit durch den Entwickler generische Einheiten, die für verschiedenste Anwendungen instantiiert und spezialisiert werden können.
- Komponentenorientierte Programmierung: die in Generi-C programmierten Einheiten sind immer automatisch streng von einander getrennte Komponenten mit definierten Schnittstellen, die erst für die jeweilige Anwendung in spezifischer Form zusammengefügt werden.
- Partielle Auswertung zur Übersetzungszeit: der Programmcode der in Generi-C programmierten Einheiten wird bei Instantiierung bereits zur Übersetzungszeit auf jetzt schon auswertbaren und damit zur Laufzeit überflüssigen Code hin untersucht.
Die Kombination dieser Möglichkeiten innerhalb einer mit C verwandten, hardwarenahen Systemprogrammiersprache erlaubt es, Softwareteile im Bereich der Embedded Software durch generische und komponentenorientierte Programmierung flexibel wieder verwenden zu können und zugleich aber durch die partielle Auswertung des Programmcodes zur Übersetzungszeit immer nur die für die jeweilige Anwendung tatsächlich benötigte Umfang an Ressourcen belegt wird, was insbesondere auf leistungsschwächeren Mikrocontrollersystemen nach wie vor sehr wichtig ist.
Die um einige wenigen Komponentenelemente erweiterten Programmiersprache Generi-C wird von einem dezidierten Vorübersetzer namens Composer auf ANSI-C abgebildet. Im Wesentlichen wurden nur die beiden Schlüsselwörter component und interface zur Programmiersprache C hinzugefügt, wobei die Syntax analog zu sonstigen C-Sprachelementen gehalten wurde. Eine zwingende Einbindung des C-Präprozessors ist damit nicht mehr notwendig. Durch den Composer werden Komponentendefinitionen gesteuert durch eine Komponentenkonfiguration wie folgt dargestellt auf C - und H - Quelltextdateien abgebildet.
Herausragende Eigenschaft dieser Lösung ist die generische Konfigurierbarkeit jeder damit erstellter Softwarekomponente, ohne dass der Komponentenentwickler hierzu irgendwelche Konfigurationsanweisungen angeben müsste. Dadurch kann jede Komponente ohne Mehraufwand optimal an die jeweilige Anwendung angepasst und ihr Ressourcenverbrauch minimiert werden. Somit können auch kleinste Softwarebestandteile ohne Overhead als so genannte MicroComponents wiederverwendet werden.
Eine Komponentendefinition in Generi-C gleicht syntaktisch einer komplexen Typdeklaration in C; semantisch gleicht sie aber eher einem Template in C++ (unterscheidet sich aber doch signifikant), denn hier wird noch kein Binärcode erzeugt. Eine Komponentenkonfiguration hingegen gleicht syntaktisch einer initialisierten Variablendefinition in C; semantisch aber eher der Benutzung eines Templates in C++; erst hier wird Binärcode erzeugt. Generi-C könnte somit auch Templates for C heißen.
Generi-C unterstützt die einfache Vererbung von Schnittstellen wie etwa in COM sowie die mehrfache, nicht aber die Vererbung von Programmcode wie in C++, da diese dem wesentlich stärker auf Kapselung von Informationen ausgerichteten Komponentengedanken widerspricht. Auch in der so genannten objektorientierten Programmierung wird immer häufiger mit abstrakten Basisklassen gearbeitet, um dem bekannten Fragile Base Class Problem zu entgehen - abstrakte Basisklassen sind aber nichts anderes als Schnittstellen!
Auf externe Komponenten und Schnittstellen wird über qualifizierte Namen wie in Java verwiesen. Dieses Konzept führt zu einer sehr vorteilhaften rekursiven Struktur; jeder in einer Datei zusammengefasster Satz konfigurierter und verknüpfter Komponenten kann seinerseits wieder als Komponente aufgefasst werden. Dadurch kann ein herkömmliches C-Modul, in dem sich keine Präprozessor-Anweisungen wie etwa #include finden, ohne weitere Änderungen direkt als Komponente aufgefasst und benutzt werden.
Bei der Beschreibung der Schnittstellenelemente einer Komponente können zusätzliche Attribute wie in der OSF DCE IDL angegeben werden. Dadurch wird es möglich, ein generisches Marshalling von Funktionsaufrufen darzustellen und so insbesondere Systeme mit unterschiedlichen Prioritätsebenen sowie verteilte Systeme zu unterstützen.
Ansatz unserer Lösung ist die Definition einer minimalen Erweiterung der standardisierten Programmiersprache C, um so komponentenorientierte Programmierung vom Embedded Software auf Systemebene überhaupt erst möglich und diese dadurch wesentlich besser wieder verwendbar zu machen. Durch die Möglichkeiten zur generischen Konfiguration jeder Softwarekomponente und den dadurch gegebenen Möglichkeiten zur Anpassung von Softwarekomponenten an eine bestimmte Anwendung unter Minimierung des Ressourcenverbrauches eignet sich unsere Lösung ideal für low-end Embedded Systems mit sehr begrenzten Ressourcen.
Unser Ansatz bietet gegenüber dem Versuch, wieder verwendbare, anpassbare Komponenten mit Hilfe von C++-Templates zu realisieren den Vorteil, wirklich in sich geschlossene Komponenten definieren zu können, die für sich vollständig geprüft und ausgetestet werden können, während bei der Benutzung von C++-Templates sogar viele Prüfungen durch den Compiler erst bei der Instantiierung der Templates, also der Benutzung durch den Anwender durchgeführt werden können, woraufhin dieser gegebenenfalls Fehlermeldungen mit dem Bezug auf den Template-Code erhält, so dass sich über C++-Templates nie wirklich abgeschlossene Komponenten verwirklichen lassen.
Bereits existierende Komponentenmodelle für Embedded Software (z.B. ECOS Component Model, Koala, Knit, TinyOs/nesC, Real-time Corba, Minimal Corba) sind oftmals speziell für bestimmte Projekte, bestimmte Branchen, bestimmte Plattformen oder bestimmte Compiler entwickelt worden und damit erstellte Komponenten sind nicht wirklich allgemein selbst auf ressourcenbeschränkten 8-Bit-Mikrocontrollern wieder verwendbar.
Einen
weitergehenden technischen Artikel mit einer detaillierteren Vorstellung
unserer Komponententechologie im PDF-Format finden Sie
hier.
Wenn Sie weitergehendes Interesse an Generi-C haben und ausführliche Informationen sowie eine Vorab-Version unseres Composers wünschen, kontaktieren Sie uns bitte hierüber.