Bei der Entwicklung von Libraries und Devices unter "AmigaOS 4" gibt
es sehr viele Parallelen zum Vorgängersystem. Änderungen gibt
es natürlich am Startup-Code und dessen Umgebung. Diese Komponenten
soll dieser Artikel Schritt für Schritt vorstellen. Dabei wird aber
praktisch die komplette Vorbereitung von "idltool" übernommen.
Jede Library und jedes Device haben vier genormte Funktionen am Anfang,
die vom AmigaOS benutzt werden. Dies sind Obtain zum Öffnen der Bibliothek,
Release zum Schließen und Expunge zum Entfernen der Bibliothek aus
dem Speicher.
Die drei Funktionen gab es auch schon unter OS3.x. Neu hinzugekommen
ist die Option Clone, die zum Duplizieren des Interfaces verwendet werden
soll. "AmigaOS 4" macht davon noch keinen Gebrauch. Benutzt
wird die Interface-Funktion aber bereits bei der application.library (u.a.
Docky-Programmierung).
XML-Datei
als Grundlage
Was früher die Funktions-Definitionen (FD) mit den Informationen
über Offset und Argumente waren, wurden bei "AmigaOS 4"
durch Files im XML-Format ersetzt. XML stellt lediglich einen Container
für die Daten dar, wobei aber nicht definiert ist, wie die Daten
verarbeitet werden. Dazu bedarf es so genannter Übersetzer. Unter
OS4 übernimmt "idltool" die Interpretation. Es handelt
sich hierbei um ein sehr leistungsfähiges Tool, das aus der XML-Beschreibung
die include- und inline-Dateien erzeugt und zusätzlich auch noch
den vollständigen Library-Init-Sourcecode generiert.
Als erstes muss also die XML-Datei erstellt werden. Sie hat einen sehr
einfachen Aufbau und würde für eine demo.library wie in Listing
1 aussehen.
Die meisten Felder dürften selbsterklärend sein und einzelne
Namen tauchen später wieder im Quellcode auf. Ersetzen Sie "demo"
einfach durch einen beliebigen anderen Namen, wenn eigene Libraries erstellt
werden. Bei Addiere handelt es sich bereits um die erste eigene Funktion.
Für jede zusätzliche Funktion ist ein entsprechender Block zu
erstellen. Über result wird der Rückgabetyp definiert, void
steht für eine leere Rückgabe. Entsprechend ist für jedes
Argument eine weitere Zeile mit arg notwendig. Bei Funktionen ohne Übergabe-Argumente
ist entsprechend überhaupt keine arg-Zeile vorhanden. Eine Besonderheit
sind noch die Funktionen mit variabler Argumentanzahl (z.B. SNPrintf).
Hier ist statt der arg-Zeile eine vararg-Anweisung vorzunehmen. Diese
könnte so aussehen:
<vararg name="tags" type="Tag"/>
Nicht vergessen werden darf das Schließen des method-Tags nach
jeder einzelnen Funktionsbeschreibung. Im include-Block können Libraries
angegeben werden, die so auch als include-Anweisung in den einzelnen Files
erzeugt werden. Diese Dateien werden nicht automatisch angelegt, sondern
müssen bereits vorhanden sein bzw. noch erstellt werden. Abzulegen
sind dort Defines und Strukturen, die im Zusammenhang mit der neuen Library
stehen.
Falls die Bibliothek nicht nur OS4-Programmen zur Verfügung stehen
soll, sondern auch noch alten 3.x-Programmen im Emulations-Modus, dann
ist etwas mehr Arbeit notwendig, um auch einen 68k-Einsprung zu ermöglichen.
In diesem Fall ist eine SFD-Datei zu erstellen, aus der mit Hilfe des
Tools "fdtrans" die XML-Datei automatisch erstellt wird.
Wird die Library nur von PPC-nativen Programmen verwendet, ist der Umweg
über die SFD-Datei nicht notwendig. Alte 68k-Libraries können
direkt von PPC-Programmen angesprungen werden, wobei die Emulationsschicht
von "AmigaOS 4" sich automatisch um das Interface kümmert.
idltool
in Aktion
Aus der XML-Datei werden mit idltool Dateien und Includes generiert. Als
Aufruf gilt für das Beispiel:
idltool -all demo.xml
Dabei erzeugt das Tool im Verzeichnis demo_files verschiedene Dateien.
Eine Übersicht mit den Files finden Sie in der Tabelle "Erzeugte
Includes". Die Definition der Funktion zum
Addieren finden Sie in Listing 2. Im Verzeichnis include finden Sie drei
weitere Dateien:
proto/demo.h
inline4/demo.h
interfaces/demo.h
Diese drei Dateien sind bei öffentlichen Libraries weiterzugeben
und sollten in das Verzeichnis SDK:include kopiert werden. Die Includes
sind vollständig und müssen nicht extra bearbeitet werden.
Zusätzlich muss man noch die Datei libraries/demo.h anlegen, die
bei Bedarf eine öffentliche Library-Basis enthält. Sie kann
zusätzliche Strukturen und Defines festlegen. Im Moment reicht es
aber aus, eine leere Datei zu erstellen, da unsere demo.library (noch)
keine zusätzlichen Angaben hat.
Falls später zusätzliche Funktionen eingefügt werden,
dann muss entweder idltool erneut aufgerufen werden oder die Änderungen
auch von Hand in den oben aufgeführten Includes vorgenommen werden.
Diese Methode ist aber recht mühsam und fehleranfällig. Bei
wiederholter Erzeugung der Dateien müssen Sie eigene Änderungen
unbedingt sichern. idltool erzeugt immer alle Dateien komplett neu und
vorgenommene Änderungen gehen verloren. Bei Erweiterungen also zuerst
alle Dateien sichern, diese komplett von idltool erzeugen lassen und eigene
Erweiterungen von den gesicherten Dateien in die neuen Dateien umkopieren.
Übersetzen lässt sich die Library ganz einfach, da bereits
ein Makefile generiert wurde. Falls die Includes nur lokal vorliegen,
muss jedoch noch ein Suchpfad darauf angelegt werden, damit sie der Compiler
auch findet. Am einfachten wird dazu im Makefile die CFLAGS-Einstellung
erweitert um
-I ../include
Werden die Includes allerdings ins SDK-Verzeichnis umkopiert, kann dieser
Suchpfad entfallen. Zur Erzeugung der Bibliothek gehen Sie nach diesem
Muster vor:
cd demo_files
make revision
make
Der Aufruf make revision erzeugt im Verzeichnis demo_files die Datei
demo.library _rev.h
Sie enthält die Versionsangaben zur Library. Jeder weitere Aufruf
setzt die Revisionsnummer um einen Zähler nach oben. make compiliert
dann alle Komponenten der Library und erstellt auch sofort die demo.library.
Erzeugte Includes |
Makefile |
Ein vollständiges Makefile, das das Übersetzen
und Linken der Bibliothek einfach über make ermöglicht.
|
init.c |
Library-Init-Code mit den Obtain-, Release-
und Expung-Funktionen. Normalerweise ist keine Bearbeitung
notwendig. In der libInit-Funktion sind bei Bedarf noch
benötigte Systembibliotheken zu öffnen. Im erzeugten
Sourcecode ist als Beispiel bereits die utility.library
als Kommentar vorhanden. Hinweis: Die Bibliotheken müssen
in der libExpunge-Funktion auch wieder geschlossen werden. |
demo_vectors.c |
Enthält Prototypen für Obtain
und Release, sowie den eigenen Funktionen. |
main/Obtain.c |
Dieses Include ist für zusätzliche
Aktionen vorgesehen, die beim Öffnen der Library
erfolgen sollen. Beispiel: Anlegen und Initialisierung
lokaler Daten für diese Instanz. |
main/Release.c |
Zusätzliche (Aufräum-) Aktionen
für das Schließen der
Library einbinden. |
main/Addiere.c |
Öffentliche Additions-Funktion
der Library. |
|
|
AutoInit
für die Bequemlichkeit
Damit die Arbeit mit idltool komfortabel ist, erzeugt das Tool auch noch
den Sourcecode für das automatische Öffnen der demo.library.
Dabei spricht man vom AutoInit-Code, der muss anschließend nur noch
kompiliert werden. Die beiden Aufrufe zur Erzeugung des AutoInit-Codes
und zur Übersetzung lauten:
gcc -I include-c autoinit_demo_base.c-o autoinit_demo_base.o
gcc -I include-c autoinit_demo_main.c-o autoinit_demo_main.o
Um die erzeugten Objektdateien in das Archivformat zu bekommen, bedient
man sich noch der Kommandos:
ar rcs libdemo_auto.aautoinit_demo_base.oautoinit_demo_main.o
und
ranlib libdemo_auto.a
Als Ergebnis erhalten Sie die Datei libdemo_auto.a -sie wird in das Verzeichnis
gcc/lib kopiert. Der gcc-Compiler findet dann die neue Bibliothek automatisch.
Alternativ lässt sich mit Hilfe des Parameters -L ein zusätzlicher
Suchpfad für die Libraries an den gcc-Compiler übergeben.
Neue
Library im Einsatz
Zum Schluss dieses Artikels soll natürlich auch noch die neue Bibliothek
zur Anwendung kommen. Aufgrund des Autoinit-Codes können Sie auf
das manuelle Öffnen der Library verzichten. Sie benutzen die Funktion
direkt wie das Beispiel in Listing 3 zeigt.
Die Übersetzungsanweisung für die Erzeugung des Demos lautet
dann :
gcc testapp.c -I include-o testapp-L . -ldemo_auto
Die Option -ldemo_auto öffnet automatisch die vorher erstellte Bibliothek
demo.
library und das -L sorgt dafür, dass der Autoinit-Code im aktuellen
Verzeichnis gesucht wird. Alternativ geben Sie den direkten Pfad zu einem
Verzeichnis mit den verwendeten Bibliotheken an.
Damit das Programm funktioniert, ist jetzt nur noch eine Aktion notwendig:
Die demo.library muss ins aktuelle Verzeichnis mit dem Programm oder nach
LIBS: kopiert werden. So findet das Demo-Programm die Bibliothek.
Devices
entwickeln
Bisher war immer nur von den Libraries die Rede. Devices unterscheiden
sich grundsätzlich nicht grundlegend von den Libraries. Allerdings
verfügen sie über ein erweitertes Sortiment an Basisfunktionen
und können Aufgaben auch asynchron zur Anwendung ausführen.
Der Funktionsaufruf SendIO() kehrt sofort zurück und wir werden erst
später durch eine Nachricht (IORequest) über das Ende der Aktion
und evtl. über Ergebniswerte informiert. Dagegen führt DoIO()
die Funktion synchron aus und liefert sofort das Ergebnis. In der XML-Datei
ist die Zeile mit library wie im folgenden Beispiel anzupassen
<library name="demo"basename="DemoBase"basetype="DemoBase"openname="demo.device">
Aufgrund des Doctypes erkennt idltool den Unterschied zwischen Library
und Device. Falls das Device auch Funktionen enthält (z.B. timer.device),
sind entsprechend wieder method-Blöcke je Funktion in die XML-Definition
einzutragen.
Mehr soll an dieser Stelle zu Devices nicht gesagt werden, da man eigentlich
nur in Verbindung mit Hardware-Devices implementieren muss. Die Benutzung
von Devices war bereits Thema des Kursteils über die Programmierung
des timer.device [1].
Alle Beispiele und die Quelltexte finden Sie auf der nächsten Heft-CD
zum Amiga Magazin.
lb
Literatur:
[1] |
Zur richtigen Zeit, Michael Christoph,
Amiga Magazin 5/2005 |
|