Tłumaczenie rozdziału 1 i 2 z dokumentu "Migration Guide" załączonego do SDK do systemu AmigaOS 4.
Wstęp do pisania pod systemy operacyjne AmigaOS4.x.
1. Wprowadzenie
Żeby być w pełni kompatybilnym z klasycznym API istnieje kilka zasad, które programista powinien przestrzegać portując programy z komputerów z procesorami 68k i AmigaOS3.x na nowe z procesorami PowerPC i AmigaOS4.x. Ten dokument zawiera zarys procesu jak również wskazuje na kilka potencjalnych pułapek i problemów.
2. Poziom Kodu Źródłowego
2.1. Pliki Nagłówkowe
Pliki nagłówkowe były rzeczą problematyczną pod OS3.x ponieważ było wiele różnych kompilatorów i większość z nich miała tendencję do używania własnego schematu nazewnictwa i była "przyklejona" do systemu operacyjnego. Dobrze znane kompilatory SAS/C oraz StormC używały #pragmas podczas gdy GCC używał funkcji inline lub dyrektyw #define. AmigaOS 4 obecnie używa dwóch systemów kompilatorów (GNU GCC oraz pakiet VBCC) i oba używają tego samego schematu dla plików nagłówkowych.
By użyć biblioteki pod AmigaOS 4 po prostu załączasz jego plik proto, jako dodatek do każdego pliku który może być potrzebny. Na przykład, żeby użyć Okienek i Ekranów Intuition mógłbyś zastosować następujący program:
#include
#include
#include
Plik proto załącza niezbędne nagłówki, które mogą zależeć od kompilatora, który używasz. Po prostu załączając plik proto zapewniasz maksymalną kompatybilność pomiędzy różnymi kompilatorami.
Kilka symbolów preprocesora określa sposób w jaki załączane są systemowe przypisania. Tabela 1 podsumowuje te symbole. Zwykle definuje się je w pliku Makefile, jednakże mogą tez być zawarte w dyrektywach #define. Nie przejmuj się jeśli nie rozumiesz wszystkiego w treści tabeli; zostanie to wyklarowane w dalszej części dokumentu.
_USE_INLINE_
Ten symbol powoduje, że załączony zostaje również plik inline4. Plik inline4 zawiera makra preprocesora do funkcji, które w klasyczny sposób definują wywoływanie systemowych funkcji (tzn. funkcji, a nie metod). Pierwotną intencją jest kompatybilność ze starymi kodami źródłowymi, jak również ogólna kompatybilność.
__NOLIBBASE__
Zapobiega definicji bazy biblioteki (library base) załączonej do pliku proto. Zwykle plik proto deklaruje zewnętrzny symbol dla bazy biblioteki.
__USE_BASETYPE__
Jeśli __NOLIBBASE__ nie jest zdefiniowany, ten symbol określa czy baza biblioteki jest określona swoim realnym type, czy bazowym typem abstrakcyjnym klasy zasobu (struktura Library bądź Device). Tyle implementory bibliotek powinny używać tego symbolu; zwykle, wszystkie struktury baz bibliotek są prywatne i nie powinny być czytane. Zwyczajowo zalecane jest deklarowanie wszystkich baz bibliotek jako struktury Library, a wszystkie bazy urządzeń jako struktury Device.
__NOGLOBALIFACE__
Pliki proto dla bibliotek, które deklarują statyczny globalny interfejs (jak wszystkie "klasyczne" biblioteki) zwykle również deklarują wskaźnik do interfejsu wewnatrz pliku proto, chyba że ten symbol zostanie zdefiniowany. Zwykle użyjesz tego symbolu tylko w przypadku gdy chcesz przechowywać wskaźnik do interfejsu gdzieś indziej, na przykład w bazie biblioteki.
Mówiąc o symbolach preprocesora warto wspomnieć, że kompilator definiuje symbol preprocesora kiedy platformą docelową jest AmigaOS 4.x __amigaos4__ i możesz używać tego symbolu do kompilacji warunkowej.
2.2 Bazy Bibliotek i Wskaźniki do Interfejsu
Bazy bibliotek powinny być normalnie zadeklarowane wewnątrz kodu źródłowego. Plik proto zwykle deklaruje wymaganą bazę biblioteki samodzielnie. Jeśli chcesz mimo wszystko sam zadeklarować bazę, powinieneś zdefiniować symbol preprocesora __NOLIBBASE__ by plik proto nie deklarował tej bazy.
W przeciwieństwie do starego systemu, AmigaOS 4 ma trochę inny sposób na wywoływanie funkcji bibliotecznych. Stary system używał do wywoływania funkcji bibliotecznej relatywny skok do tabeli skoków położonej bezpośrednio przed bazą biblioteki. AmigaOS 4 zachowuje te tablice skoków tylko do kompatybilności wstecz - tylko funkcje 68k są wywoływane nadal w ten sposób. Nowy OS przechowuje tablice skoków w oddzielnym wskaźniku nazywanym "Wskaźnikiem do Interfejsu", lub w skrócie "interfejsem". Zasadniczo interfejs jest strukturą z informacjami administracyjnymi oraz mnóstwem wskaźników inline do funkcji. Biblioteka może wyeksportować więcej niż jeden wskaźnik do interfejsu (zwykle eksportuje co najmniej dwa). Prawie wszystkie biblioteki eksportują swój interfejs o nazwie "main". Dokładny typ tego interfejsu zależy od biblioteki. Na przykład exec.library eksportuje główny interfejs typu "struct ExecIFace *" (Zauważ, że teoretycznie byłoby możliwe wyeksportowanie interfejsu typu "struct ExecIFace *" przez inną bibliotekę).
Tak jak bazy bibliotek wcześniej były używane do wywoływania funkcji bibliotecznych, tak konwencją jest, że globalna zmienna jest używana by uczynić wskaźnik do ExecIFace dostępny we wszystkich funkcjach Twojego programu. Nazwa zmiennej jest tworzona poprzez poprzedzenie nazwy bazy biblioteki ("Exec" w tym przykładzie) przez duże I. Toteż, globalny wskaźnik do ExecIFace (struct ExecIFace *) może być nazywany IExec. Zauważ, że to jest po prostu konwencja wprowadzona w plikach proto. Nie musisz w ogóle używać globalnych wskaźników do interfejsów, jak również nie musisz używać globalnych wskaźników do bibliotek (ani teraz w AmigaOS 4, ani w AmigaOS 3.9 czy wcześniejszych wersjach).
2.3 Konsystencja Typów
Podrecznik do architektury PowerPC zwykle używa słowa "word" do określenia wartości 32-bitowej. Jednakże klasyczny AmigaOS jako typ WORD oraz UWORD uważał wartość 16-bitową ze znakiem bądź bez znaku. Podobnie, 8-bitowa wartość zwykle była określana jako BYTE lub UBYTE, a 32-bitowe "słowa" były nazywane LONG oraz ULONG. Nie istniały wartości 64-bitowe. By wyklarować nazewnictwo typów bazowych, te typy zostały unieważnione w AmigaOS 4. Nowe typy są konsekwentnie nazywane int or uint po czym następuje liczba bitów, np. uint32 oznacza 32-bitową wartość bez znaku. Podobnie, typy zostały rozszerzone by zawierać wartości 64-bitowe. Tabela 2 przedstawia nowe typy oraz "klasyczne" typy, które zastępują. Zauważ, że stare typy są nadal dostępne poprzez definicje preprocesora, ale nie powinny być już używane w nowym kodzie.
Nowy Typ Stary Typ Znaczenie
int8/uint8 BYTE/UBYTE 8 bitowa liczba całkowita ze znakiem/bez znaku
int16/uint16 WORD/UWORD 16 bitowa liczba całkowita ze znakiem/bez znaku
int32/uint32 LONG/ULONG 32 bitowa liczba całkowita ze znakiem/bez znaku
int64/uint64 Nie istniał 64 bitowa liczba całkowita ze znakiem/bez znaku
float32 FLOAT 32 bitowa liczba zmiennopozycyjna pojedyńczej przecyzji
float64 DOUBLE 64 bitowa liczba zmiennopozycyjna podwójnej precyzji