Difference between revisions of "Organizacja API MorphOS-a"

From MorphOS Library

(Translation in progress.)
(Translation finished.)
 
(8 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
''Grzegorz Kraszewski''
 
''Grzegorz Kraszewski''
 
----
 
----
<small>Ten artykuł w innych językach [[MorphOS API and Its Organization|angielski]]</small>
+
<small>Ten artykuł w innych językach: [[MorphOS API and Its Organization|angielski]]</small>
  
  
 
API (interfejs programisty aplikacji) systemu operacyjnego składa się zazwyczaj z tysięcy funkcji. MorphOS nie jest tu wyjątkiem. Jego kernel nie jest jednak monolityczny, API jest funkcjonalnie i fizycznie podzielone na biblioteki. Tylko kilka największych bibliotek zawiera więcej niż 50 funkcji. Zestaw najważniejszych bibliotek znajduje się w startowym pliku kernela (ang. ''boot image''). Pozostałe umieszczone są na partycji systemowej dysku w katalogu ''MOSSYS:Libs'' (biblioteki dostarczane z systemem) i ''SYS:Libs'' (zewnętrzne biblioteki dodatkowe). Biblioteki znajdujące się na dysku są ładowane do pamięci na żądanie. Wszystkie te biblioteki są współdzielone, co oznacza, że wszystkie procesy używające danej biblioteki wykonują ten sam kod, umieszczony w pamięci jednokrotnie.
 
API (interfejs programisty aplikacji) systemu operacyjnego składa się zazwyczaj z tysięcy funkcji. MorphOS nie jest tu wyjątkiem. Jego kernel nie jest jednak monolityczny, API jest funkcjonalnie i fizycznie podzielone na biblioteki. Tylko kilka największych bibliotek zawiera więcej niż 50 funkcji. Zestaw najważniejszych bibliotek znajduje się w startowym pliku kernela (ang. ''boot image''). Pozostałe umieszczone są na partycji systemowej dysku w katalogu ''MOSSYS:Libs'' (biblioteki dostarczane z systemem) i ''SYS:Libs'' (zewnętrzne biblioteki dodatkowe). Biblioteki znajdujące się na dysku są ładowane do pamięci na żądanie. Wszystkie te biblioteki są współdzielone, co oznacza, że wszystkie procesy używające danej biblioteki wykonują ten sam kod, umieszczony w pamięci jednokrotnie.
  
==Libraries Overview==
 
  
MorphOS comes with over 100 different libraries. Not all of them are listed below, just the most common ones. Browse the system autodocs in the SDK for more.
+
==Przegląd najważniejszych bibliotek==
  
* '''exec.library''', the master library. This is the system core, responsible for process scheduling, control and creation, communication between processes, memory management, managing other libraries and overall system control. This is the only library which is always open and cannot be closed.
+
Dystrybucja MorphOS-a zawiera ponad 100 różnych bibliotek. Oczywiście poniżej wymienione są tylko najważniejsze. Opis pozostałych można znaleźć w dokumentacji znajdującej się w SDK.
  
* '''dos.library''', responsible for file and console input/output. Provides an interface to advanced filesystem functions (like scanning directories for example). Cooperates with the ''exec.library'' in process creation. Delivers basic system time services.
+
* '''exec.library''', główna biblioteka systemu, tu znajdują się podstawowe elementy systemu takie jak zarządzanie procesami i zarządzanie pamięcią, ładowanie innych bibliotek, kontrola stanu systemu i tak dalej. Jako jedyna biblioteka jest zawsze otwarta i nie da się jej zamknąć.
  
* '''graphics.library''', is responsible for low-level graphics functions like drawing pixels and other primitives, copying rectangular blocks of display, scrolling etc. Many programs do not use it directly.
+
* '''dos.library''', odpowiada za operacje wejścia/wyjścia na plikach i innych urządzeniach (np. konsola tekstowa). Jest interfejsem do bardziej złożonych funkcji systemów plików (np. przeszukiwanie katalogów). Współdziała z ''exec.library'' przy tworzeniu procesów. Zawiera podstawowe funkcje zegara czasu rzeczywistego.  
  
* '''intuition.library''', delivers intermediate level graphics interface objects like screens and windows. Interfaces to user input devices (mouse and keyboard to name a few). Provides very basic user controls (gadgets). Provides also BOOPSI (''Basic Object Oriented System for Intuition''), a language independent object oriented programming framework, used commonly by other components.
+
* '''graphics.library''', zawiera niskopoziomowe funkcje graficzne, np. rysowanie pojedynczych pikseli i prostych figur geometrycznych, kopiowanie prostokątnych obszarów obrazu, przewijanie (scroll) itp. Wiele programów nie korzysta z niej bezpośrednio.
  
* '''muimaster.library''', the main interface to MUI (''Magic User Interface''), which is the MorphOS high level GUI toolkit. Provides a complete, object oriented framework (based on BOOPSI) for GUI driven applications and a rich set of GUI objects.  
+
* '''intuition.library''', zarządza podstawowymi obiektami interfejsu użytkownika, takimi jak ekrany i okna. Zajmuje się obsługą urządzeń wejściowych (mysz, klawiatura i inne). Zawiera w sobie [[Rzut oka na BOOPSI|BOOPSI]] (''Basic Object Oriented System for Intuition''), który jest bazą dla niezależnego od języka programowania obiektowego. Baza ta jest używana przez wiele innych komponentów systemu.
  
* '''locale.library''', is responsible for system and application internationalization. This simple yet powerful subsystem allows for supporting multiple language versions of a program with a single executable, also provides localization data such as date format, local currency, timezone, number grouping and more.
+
* '''muimaster.library''', jest głównym interfejsem MUI (''Magic User Interface'') &ndash; podstawowej wysokopoziomowej biblioteki do tworzenia graficznego interfejsu użytkownika programów. MUI jest rozwinięciem BOOPSI, daje programiście kompletny szkielet do programowania obiektowego sterowanego zdarzeniami i dostarcza bogaty zestaw gadżetów (kontrolek).
  
* '''bsdsocket.library''' is an interface for TCP/IP networking, compatible with BSD sockets. What is unusual with this library, is that it is neither built into the kernel, nor placed on disk. The TCP/IP stack creates it in memory dynamically.
+
* '''locale.library''', służy do tworzenia wielojęzycznych wersji programów. Oprócz umożliwienia prostej lokalizacji interfejsu użytkownika, pozwala również programom na pobranie od systemu ogólnych danych specyficznych dla kraju i języka użytkownika (np. waluta, format daty, strefa czasowa, grupowanie cyfr w dużych liczbach itp.)
  
 +
* '''bsdsocket.library''', jest biblioteką obsługującą protokół TCP/IP, kompatybilną z interfejsem BDS sockets. Co ciekawe biblioteka ta nie znajduje się ani w kernelu ani na dysku &ndash; jest tworzona dynamicznie w pamięci przez stos TCP/IP.
  
==How to Use a Library in an Application==
 
  
In typical cases it is pretty automatic. The only thing which has to be done is including the main library header file, which is ''<proto/[libname].h>'', for example ''<proto/exec.h>'', ''<proto/muimaster.h>'' and so on. Library opening and closing is handled automatically by the startup code provided by either ''libnix'' or ''ixemul.library''. Then one can just use functions from the library.
+
==Jak używać bibliotek w programach==
  
 +
Najczęściej użycie biblioteki w programie jest praktycznie automatyczne. Jedyna rzecz, jaką trzeba zrobić, to zainkludowanie głównego pliku nagłówkowego biblioteki, którego nazwa tworzona jest według schematu ''<proto/[nazwa biblioteki].h>'', na przykład ''<proto/exec.h>'', ''<proto/muimaster.h>'' i tak dalej. Otwarcie i zamknięcie biblioteki jest wykonywane automatycznie w kodzie startowym, pochodzącym z ''libnix''-a albo ''ixemul.library''. W programie można więc po prostu używać funkcji danej biblioteki.
  
A few big libraries have separate subdirectories in the system include tree. Examples of such libraries are ''exec.library'', ''dos.library'' and ''graphics.library''. Header files in these directories contain definitions of constants, data structures, attributes etc. used by the library, divided by functionality. Including of these headers depends on which functions are used in the application, for example to use ''exec.library'' memory allocation functions one has to include the ''<exec/memory.h>'' header.
+
Kilka największych bibliotek posiada własne podkatalogi w drzewie plików nagłówkowych systemu. Przykładami mogą tu być
 +
''exec.library'', ''dos.library'', czy ''graphics.library''. Pliki nagłówkowe w tych katalogach zawierają definicje stałych, struktur danych, atrybutów itp. podzielone według zastosowania. Inkludowanie tych plików w kodzie programu uzależnione jest od tego, które funkcje biblioteki są wykorzystane w programie. Przykładowo używając funkcji alokacji pamięci z ''exec.library'' powinniśmy zainkludować plik ''<exec/memory.h>''.
  
 +
Inne biblioteki mogą posiadać pojedynczy plik nagłówkowy w katalogu ''libraries''. Na przykład ''<libraries/locale.h>'' lub ''<libraries/mui.h>'' (ten drugi przykład pokazuje małą niekonsekwencję w nazewnictwie...). Ten plik może być automatycznie inkludowany z bazowego ''proto'', ale czasem musi być inkludowany ręcznie w kodzie programu.
  
Other libraries have a single header file in the ''libraries'' directory. Examples are ''<libraries/locale.h>'' or ''<libraries/mui.h>'' (the latest is some deviation from the naming rule). This single header may be automatically included from the ''proto'' file or not.
+
W kilku przypadkach automatyczna obsługa bibliotek nie działa, albo nie można z niej skorzystać:
  
 +
* Dodatkowe biblioteki pisane przez niezależnych programistów. Większość z nich nie jest dodana do listy bibliotek otwieranych automatycznie.
 +
* Program korzystający z własnego kodu startowego (linkowany z opcją '''&minus;nostartfiles''').
 +
* Biblioteki otwierane w podprocesie.
 +
* Biblioteki otwierane w programie dynamicznie na żądanie.
 +
* Baza biblioteki zdefiniowana w kodzie programu. W tym przypadku funkcja automatycznego otwierania jest wyłączana dla tej konkretnej biblioteki.
  
There are a few cases, where automatic library handling does not work, or cannot be used.
+
W powyższych przypadkach biblioteka musi być otwarta i zamknięta ręcznie.
  
* Third party libraries. Most of them are not included in the autoopen feature.
 
* Custom startup code (linking with '''&minus;nostartfiles''').
 
* Opening libraries in a subprocess.
 
* Dynamic on-demand library opening.
 
* The library base has been defined in the application code. Autoopening for this library is automatically disabled in this case.
 
  
In all of these cases, libraries have to be handled manually.
+
==Ręczne otwieranie i zamykanie bibliotek==
  
 +
Ręczne otwieranie i zamykanie bibliotek jest proste, choć, rzecz jasna, nie tak wygodne jak automatyczne. Przy ręcznej obsłudze potrzebna jest zmienna, tak zwana '''baza biblioteki'''. Następnie korzystamy z dwóch funkcji ''exec.library'': ''OpenLibrary()'' i ''CloseLibrary()''.
  
==Manual Library Opening and Closing==
+
Baza biblioteki jest zdefiniowana w jej pliku ''proto'' (głównym pliku nagłówkowym biblioteki), jako zmienna globalna. Jest ona wskaźnikiem na strukturę ''Library''. Strukturę tę powinno się zasadniczo traktować jako "czarną skrzynkę". W zmiennej umieszczamy wynik zwrócony przez funkcję ''OpenLibrary()'', trzeba to zrobić zanim wywołamy jakąkolwiek funkcję otwieranej biblioteki. W momencie, gdy biblioteka nie jest już potrzebna, zamykamy ją funkcją ''CloseLibrary()'', podając jej bazę biblioteki jako argument. Oto przykład użycia hipotetycznej biblioteki ''foobar.library'' w programie:
  
While not as convenient as automatic handling, manual opening and closing of libraries is not very complicated. A ''library base'' variable has to be defined, then two functions from ''exec.library'': ''OpenLibrary()'' and ''CloseLibrary()'' have to be used.
+
/* wewnątrz <proto/foobar.h> */
 +
 +
struct Library *FoobarBase;
  
 +
/* wewnątrz kodu programu */
 +
 +
#include <proto/foobar.h>
 +
 +
if (FoobarBase = OpenLibrary((STRPTR)"foobar.library", 7))
 +
{
 +
  /* tu można używać funkcji z biblioteki */
 +
 +
  CloseLibrary(FoobarBase);
 +
}
  
The library base is defined in its ''proto'' file (the main header) as a global variable. It is a pointer to a ''Library'' structure, which should be treated as an opaque pointer. The result returned by ''OpenLibrary()'' should be placed in the library base before any function of the library is called. Then, when the library is no longer needed, it should be closed with ''CloseLibrary()'' using its base as the argument. The layout for using the hypothetical ''foobar.library'' is as follows:
+
Funkcja ''OpenLibrary()'' ma dwa parametry. Pierwszy to nazwa biblioteki do otworzenia. Podaje się samą nazwę, bez ścieżki. MorphOS szuka biblioteki w kilku standardowych lokacjach, w następującej kolejności:
  
 
<tt>/* inside <proto/foobar.h> */
 
 
 
struct Library *FoobarBase;
 
 
 
/* inside application */
 
 
 
&#35;include <proto/foobar.h>
 
 
 
if (FoobarBase = OpenLibrary((STRPTR)"foobar.library", 7))
 
 
{
 
 
&nbsp;&nbsp;/* use library functions here */
 
 
 
&nbsp;&nbsp;CloseLibrary(FoobarBase);
 
 
}</tt>
 
 
 
The ''OpenLibrary()'' call takes two parameters. The first one is just the name of the library to be opened. It is only the name, without path. MorphOS searches a few locations for the library in the following order:
 
 
* MOSSYS:Libs/
 
* MOSSYS:Libs/
 
* LIBS:
 
* LIBS:
* current directory of the application
+
* katalog bieżący programu
 
* PROGDIR:Libs/
 
* PROGDIR:Libs/
In the fourth path ''PROGDIR:'' is an automatic assign pointing to the directory containing the application executable.
 
 
 
The second parameter of ''OpenLibrary()'' is the minimum required version. Zero here opens any version, any positive number means "this version or higher". There is no straightforward way for requesting a particular version of a library. It can be noticed that this approach only works if newer versions of a library are always backward compatible with older ones. On the other hand it avoids having multiple versions of the same library in the system, which is a common problem with Linux shared objects.
 
 
 
The value returned by ''OpenLibrary()'' should be always checked against NULL. Even a library built into the boot image may fail to open (because of a memory shortage for example, or having too low a version). Printing some error message in case of a fail is definitely a good idea.
 
 
  
Every successful ''OpenLibrary()'' call must be matched with ''CloseLibrary()''. Resource leak is created otherwise.
+
W czwartej ścieżce ''PROGDIR:'' jest automatycznym przypisaniem wskazującym na katalog, w którym znajduje się plik wykonywalny programu.  
  
 +
Drugi parametr ''OpenLibrary()'' to minimalna wymagana wersja biblioteki. Podanie zera pozwala na dowolną wersję, każda liczba większa od zera oznacza "ta wersja lub wyższa". Nie ma prostego sposobu na zażądanie konkretnej wersji biblioteki. Jak łatwo zauważyć takie podejście do bibliotek wymaga, aby nowsze wersje były zawsze kompatybilne wstecz ze starszymi. Z drugiej strony pozwala to uniknąć istnienia w systemie wielu wersji tej samej biblioteki, co jest powszechnym problemem z linuksowymi bibliotekami w formacie ''shared object''.
  
There are two special cases for manual library opening and closing: ''exec.library'' and ''dos.library''. The first one is always open and cannot be closed, as stated above. The library base for it (named ''SysBase'') is defined and initialized in the startup code. If declared manually in an application's source code, it should be declared as an ''extern''. The ''dos.library'' is opened and closed as with any other library, but because the startup code needs it, the ''DOSBase'' is already defined and initialized there. As a result the application does not need to open ''dos.library'' before using it. If declared in an application, ''DOSBase'' should be an ''extern'' too.
+
Program powinien zawsze sprawdzić, czy wartość zwracana przez ''OpenLibrary()'' jest różna od zera. Nawet otwarcie biblioteki wbudowanej w kernel systemu może się nie powieść (z powodu braku pamięci lub za niskiej wersji biblioteki). Wypisanie w takim przypadku komunikatu o błędzie jest z pewnością dobrym pomysłem.
  
 +
Każde udane otwarcie biblioteki przez ''OpenLibrary()'' powinno mieć odpowiadające mu wywołanie ''CloseLibrary()''. Pozostawienie otwartej biblioteki może skutkować wyciekiem pamięci, uniemożliwia też usunięcie biblioteki z pamięci (tzw. ''flush'').
  
<small>As with the Amiga historical heritage, some of the most important library bases (''SysBase'', ''DOSBase'', ''IntuitionBase'', ''GfxBase'' and a few more) are not defined as ''struct Library*'' but as pointers to library specific structures. Direct poking of these structures was unavoidable in early AmigaOS versions. In MorphOS it is neither needed nor recommended.
+
Przy ręcznym otwieraniu bibliotek mamy do czynienia z dwoma przypadkami specjalnymi: ''exec.library'' i ''dos.library''. Pierwsza z tych bibliotek jest zawsze otwarta i nie da się jej zamknąć, jak już wcześniej wspomniano. Baza tej biblioteki (o nazwie ''SysBase'') jest zdefiniowana i zainicjalizowana w kodzie startowym. Jeżeli jest ręcznie deklarowana w kodzie programu, musi być zadeklarowana ze słowem kluczowym ''extern''. Biblioteka ''dos.library'' jest otwierana i zamykana jak każda inna, ale ponieważ używa jej kod startowy, jej baza (''DOSBase'') jest zdefiniowana i inicjalizowana w tymże kodzie. W rezultacie program nie musi otwierać ''dos.library'' przed jej użyciem, ani zamykać na zakończenie. Jeżeli ''DOSBase'' jest zadeklarowana w kodzie aplikacji, również należy ją zadeklarować jako ''extern''.
One can avoid the above definitions (which forces unnecessary typecasting in ''OpenLibrary()'' and ''CloseLibrary()'') by #defining __NOLIBBASE__ symbol before including ''proto'' files. This disables library bases definitions. All bases can (and must) be then explicitly defined in the code as pointers to ''struct Library''.
 
  
  
Also for traditional reasons, names of some library bases do not follow the ''[Libname]Base'' scheme. The most important deviations are: '''SysBase''' for ''exec.library'', '''DOSBase''' for ''dos.library'' (capitalization), '''GfxBase''' for ''graphics.library'', '''MUIMasterBase''' for ''muimaster.library'' (capitalization), '''CyberGfxBase''' for ''cybergraphics.library''. In any case the base name can be checked by looking at the library ''proto'' header.
+
<small>Dla zachowania wstecznej kompatybilności z AmigaOS, niektóre najważniejsze bazy bibliotek (''SysBase'', ''DOSBase'', ''IntuitionBase'', ''GfxBase'' i kilka innych) nie są zdefiniowane jako wskaźniki na ''struct Library'', ale jako wskaźniki na struktury specyficzne dla tych bibliotek. Konieczność bezpośredniego dostępu do pól tych struktur była nie do uniknięcia we wczesnych wersjach AmigaOS. W MorphOS-ie jest to niepotrzebne i niezalecane. Tych definicji baz bibliotek można uniknąć (wymuszają zbędne rzutowania typów przy wywołaniach ''OpenLibrary()'' i ''CloseLibrary()'') definiując stałą  __NOLIBBASE__ przed inkludowaniem plików ''proto'', co blokuje definicje baz bibliotek. Wszystkie bazy muszą być wtedy zdefiniowane w kodzie programu jako wskaźniki na ''struct Library''.
  
 +
Również z powodów historycznych niektóre bazy bibliotek nie trzymają się schematu nazewnictwa baz ''[nazwa biblioteki]Base''. Najważniejsze odchylenia od standardu to: '''SysBase''' dla ''exec.library'', '''DOSBase''' dla ''dos.library'' (duże litery), '''GfxBase''' dla ''graphics.library'', '''MUIMasterBase''' dla ''muimaster.library'' (duże litery), '''CyberGfxBase''' dla ''cybergraphics.library''. Nazwę bazy biblioteki można zawsze sprawdzić w jej pliku nagłówkowym ''proto''.
  
Using the proper base name is very important, as it is used as an '''implicit argument''' in all the calls of library functions.</small>
+
Użycie poprawnej nazwy bazy biblioteki jest bardzo ważne, ponieważ baza używana jest jako '''niejawny argument''' wszystkich wywołań funkcji z danej biblioteki.</small>

Latest revision as of 10:07, 7 April 2011

Grzegorz Kraszewski


Ten artykuł w innych językach: angielski


API (interfejs programisty aplikacji) systemu operacyjnego składa się zazwyczaj z tysięcy funkcji. MorphOS nie jest tu wyjątkiem. Jego kernel nie jest jednak monolityczny, API jest funkcjonalnie i fizycznie podzielone na biblioteki. Tylko kilka największych bibliotek zawiera więcej niż 50 funkcji. Zestaw najważniejszych bibliotek znajduje się w startowym pliku kernela (ang. boot image). Pozostałe umieszczone są na partycji systemowej dysku w katalogu MOSSYS:Libs (biblioteki dostarczane z systemem) i SYS:Libs (zewnętrzne biblioteki dodatkowe). Biblioteki znajdujące się na dysku są ładowane do pamięci na żądanie. Wszystkie te biblioteki są współdzielone, co oznacza, że wszystkie procesy używające danej biblioteki wykonują ten sam kod, umieszczony w pamięci jednokrotnie.


Przegląd najważniejszych bibliotek

Dystrybucja MorphOS-a zawiera ponad 100 różnych bibliotek. Oczywiście poniżej wymienione są tylko najważniejsze. Opis pozostałych można znaleźć w dokumentacji znajdującej się w SDK.

  • exec.library, główna biblioteka systemu, tu znajdują się podstawowe elementy systemu takie jak zarządzanie procesami i zarządzanie pamięcią, ładowanie innych bibliotek, kontrola stanu systemu i tak dalej. Jako jedyna biblioteka jest zawsze otwarta i nie da się jej zamknąć.
  • dos.library, odpowiada za operacje wejścia/wyjścia na plikach i innych urządzeniach (np. konsola tekstowa). Jest interfejsem do bardziej złożonych funkcji systemów plików (np. przeszukiwanie katalogów). Współdziała z exec.library przy tworzeniu procesów. Zawiera podstawowe funkcje zegara czasu rzeczywistego.
  • graphics.library, zawiera niskopoziomowe funkcje graficzne, np. rysowanie pojedynczych pikseli i prostych figur geometrycznych, kopiowanie prostokątnych obszarów obrazu, przewijanie (scroll) itp. Wiele programów nie korzysta z niej bezpośrednio.
  • intuition.library, zarządza podstawowymi obiektami interfejsu użytkownika, takimi jak ekrany i okna. Zajmuje się obsługą urządzeń wejściowych (mysz, klawiatura i inne). Zawiera w sobie BOOPSI (Basic Object Oriented System for Intuition), który jest bazą dla niezależnego od języka programowania obiektowego. Baza ta jest używana przez wiele innych komponentów systemu.
  • muimaster.library, jest głównym interfejsem MUI (Magic User Interface) – podstawowej wysokopoziomowej biblioteki do tworzenia graficznego interfejsu użytkownika programów. MUI jest rozwinięciem BOOPSI, daje programiście kompletny szkielet do programowania obiektowego sterowanego zdarzeniami i dostarcza bogaty zestaw gadżetów (kontrolek).
  • locale.library, służy do tworzenia wielojęzycznych wersji programów. Oprócz umożliwienia prostej lokalizacji interfejsu użytkownika, pozwala również programom na pobranie od systemu ogólnych danych specyficznych dla kraju i języka użytkownika (np. waluta, format daty, strefa czasowa, grupowanie cyfr w dużych liczbach itp.)
  • bsdsocket.library, jest biblioteką obsługującą protokół TCP/IP, kompatybilną z interfejsem BDS sockets. Co ciekawe biblioteka ta nie znajduje się ani w kernelu ani na dysku – jest tworzona dynamicznie w pamięci przez stos TCP/IP.


Jak używać bibliotek w programach

Najczęściej użycie biblioteki w programie jest praktycznie automatyczne. Jedyna rzecz, jaką trzeba zrobić, to zainkludowanie głównego pliku nagłówkowego biblioteki, którego nazwa tworzona jest według schematu <proto/[nazwa biblioteki].h>, na przykład <proto/exec.h>, <proto/muimaster.h> i tak dalej. Otwarcie i zamknięcie biblioteki jest wykonywane automatycznie w kodzie startowym, pochodzącym z libnix-a albo ixemul.library. W programie można więc po prostu używać funkcji danej biblioteki.

Kilka największych bibliotek posiada własne podkatalogi w drzewie plików nagłówkowych systemu. Przykładami mogą tu być exec.library, dos.library, czy graphics.library. Pliki nagłówkowe w tych katalogach zawierają definicje stałych, struktur danych, atrybutów itp. podzielone według zastosowania. Inkludowanie tych plików w kodzie programu uzależnione jest od tego, które funkcje biblioteki są wykorzystane w programie. Przykładowo używając funkcji alokacji pamięci z exec.library powinniśmy zainkludować plik <exec/memory.h>.

Inne biblioteki mogą posiadać pojedynczy plik nagłówkowy w katalogu libraries. Na przykład <libraries/locale.h> lub <libraries/mui.h> (ten drugi przykład pokazuje małą niekonsekwencję w nazewnictwie...). Ten plik może być automatycznie inkludowany z bazowego proto, ale czasem musi być inkludowany ręcznie w kodzie programu.

W kilku przypadkach automatyczna obsługa bibliotek nie działa, albo nie można z niej skorzystać:

  • Dodatkowe biblioteki pisane przez niezależnych programistów. Większość z nich nie jest dodana do listy bibliotek otwieranych automatycznie.
  • Program korzystający z własnego kodu startowego (linkowany z opcją −nostartfiles).
  • Biblioteki otwierane w podprocesie.
  • Biblioteki otwierane w programie dynamicznie na żądanie.
  • Baza biblioteki zdefiniowana w kodzie programu. W tym przypadku funkcja automatycznego otwierania jest wyłączana dla tej konkretnej biblioteki.

W powyższych przypadkach biblioteka musi być otwarta i zamknięta ręcznie.


Ręczne otwieranie i zamykanie bibliotek

Ręczne otwieranie i zamykanie bibliotek jest proste, choć, rzecz jasna, nie tak wygodne jak automatyczne. Przy ręcznej obsłudze potrzebna jest zmienna, tak zwana baza biblioteki. Następnie korzystamy z dwóch funkcji exec.library: OpenLibrary() i CloseLibrary().

Baza biblioteki jest zdefiniowana w jej pliku proto (głównym pliku nagłówkowym biblioteki), jako zmienna globalna. Jest ona wskaźnikiem na strukturę Library. Strukturę tę powinno się zasadniczo traktować jako "czarną skrzynkę". W zmiennej umieszczamy wynik zwrócony przez funkcję OpenLibrary(), trzeba to zrobić zanim wywołamy jakąkolwiek funkcję otwieranej biblioteki. W momencie, gdy biblioteka nie jest już potrzebna, zamykamy ją funkcją CloseLibrary(), podając jej bazę biblioteki jako argument. Oto przykład użycia hipotetycznej biblioteki foobar.library w programie:

/* wewnątrz <proto/foobar.h> */

struct Library *FoobarBase;
/* wewnątrz kodu programu */

#include <proto/foobar.h>

if (FoobarBase = OpenLibrary((STRPTR)"foobar.library", 7))
{
  /* tu można używać funkcji z biblioteki */

  CloseLibrary(FoobarBase);
}

Funkcja OpenLibrary() ma dwa parametry. Pierwszy to nazwa biblioteki do otworzenia. Podaje się samą nazwę, bez ścieżki. MorphOS szuka biblioteki w kilku standardowych lokacjach, w następującej kolejności:

  • MOSSYS:Libs/
  • LIBS:
  • katalog bieżący programu
  • PROGDIR:Libs/

W czwartej ścieżce PROGDIR: jest automatycznym przypisaniem wskazującym na katalog, w którym znajduje się plik wykonywalny programu.

Drugi parametr OpenLibrary() to minimalna wymagana wersja biblioteki. Podanie zera pozwala na dowolną wersję, każda liczba większa od zera oznacza "ta wersja lub wyższa". Nie ma prostego sposobu na zażądanie konkretnej wersji biblioteki. Jak łatwo zauważyć takie podejście do bibliotek wymaga, aby nowsze wersje były zawsze kompatybilne wstecz ze starszymi. Z drugiej strony pozwala to uniknąć istnienia w systemie wielu wersji tej samej biblioteki, co jest powszechnym problemem z linuksowymi bibliotekami w formacie shared object.

Program powinien zawsze sprawdzić, czy wartość zwracana przez OpenLibrary() jest różna od zera. Nawet otwarcie biblioteki wbudowanej w kernel systemu może się nie powieść (z powodu braku pamięci lub za niskiej wersji biblioteki). Wypisanie w takim przypadku komunikatu o błędzie jest z pewnością dobrym pomysłem.

Każde udane otwarcie biblioteki przez OpenLibrary() powinno mieć odpowiadające mu wywołanie CloseLibrary(). Pozostawienie otwartej biblioteki może skutkować wyciekiem pamięci, uniemożliwia też usunięcie biblioteki z pamięci (tzw. flush).

Przy ręcznym otwieraniu bibliotek mamy do czynienia z dwoma przypadkami specjalnymi: exec.library i dos.library. Pierwsza z tych bibliotek jest zawsze otwarta i nie da się jej zamknąć, jak już wcześniej wspomniano. Baza tej biblioteki (o nazwie SysBase) jest zdefiniowana i zainicjalizowana w kodzie startowym. Jeżeli jest ręcznie deklarowana w kodzie programu, musi być zadeklarowana ze słowem kluczowym extern. Biblioteka dos.library jest otwierana i zamykana jak każda inna, ale ponieważ używa jej kod startowy, jej baza (DOSBase) jest zdefiniowana i inicjalizowana w tymże kodzie. W rezultacie program nie musi otwierać dos.library przed jej użyciem, ani zamykać na zakończenie. Jeżeli DOSBase jest zadeklarowana w kodzie aplikacji, również należy ją zadeklarować jako extern.


Dla zachowania wstecznej kompatybilności z AmigaOS, niektóre najważniejsze bazy bibliotek (SysBase, DOSBase, IntuitionBase, GfxBase i kilka innych) nie są zdefiniowane jako wskaźniki na struct Library, ale jako wskaźniki na struktury specyficzne dla tych bibliotek. Konieczność bezpośredniego dostępu do pól tych struktur była nie do uniknięcia we wczesnych wersjach AmigaOS. W MorphOS-ie jest to niepotrzebne i niezalecane. Tych definicji baz bibliotek można uniknąć (wymuszają zbędne rzutowania typów przy wywołaniach OpenLibrary() i CloseLibrary()) definiując stałą __NOLIBBASE__ przed inkludowaniem plików proto, co blokuje definicje baz bibliotek. Wszystkie bazy muszą być wtedy zdefiniowane w kodzie programu jako wskaźniki na struct Library.

Również z powodów historycznych niektóre bazy bibliotek nie trzymają się schematu nazewnictwa baz [nazwa biblioteki]Base. Najważniejsze odchylenia od standardu to: SysBase dla exec.library, DOSBase dla dos.library (duże litery), GfxBase dla graphics.library, MUIMasterBase dla muimaster.library (duże litery), CyberGfxBase dla cybergraphics.library. Nazwę bazy biblioteki można zawsze sprawdzić w jej pliku nagłówkowym proto.

Użycie poprawnej nazwy bazy biblioteki jest bardzo ważne, ponieważ baza używana jest jako niejawny argument wszystkich wywołań funkcji z danej biblioteki.