Professional Documents
Culture Documents
PRZYKADOWY ROZDZIA
SPIS TRECI
KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG
TWJ KOSZYK
DODAJ DO KOSZYKA
CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK
CZYTELNIA
FRAGMENTY KSIEK ONLINE
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
Kylix, pierwsze narzdzie typu RAD (Rapid Application Development) dla systemu
operacyjnego Linuks jest rodowiskiem projektowym dla programowania aplikacji
graficznego interfesju uytkownika (GUI), aplikacji WWW oraz baz danych. Napisana przez
dowiadczonych programistw, ta ksika jest po prostu obowizkow pozycj dla
kadego programisty Kyliksa.
Kylix Power Solutions ma dwa gwne cele: jak najszybciej zapozna ci
z programowaniem Linuksa oraz dostarczy gotowych, sprawdzonych rozwiza
najczciej wystpujcych programistycznych problemw. Przedstawione przykady
obejmuj szeroki zakres zagadnie, od kontrolowania KDE po wzajemn komunikacj
midzy procesami. Kady przyklad obejmuje szczegowe omwienie zagadnienie
i zawiera kod rodlowy programu wykorzystujcego omawian strategi.
Ta ksika pomoe Ci w:
Jak najlepszym wykorzystaniu Kyliksa, bezporednio po wyjciu z opakowania.
Poznaniu zasadniczych rnic pomidzy programowaniem w Linuksie i w Windows
i to w rekordowo krtkim czasie.
Uruchamianiu, kontrolowaniu, zamykaniu i komunikowaniu si z innymi aplikacjami
z wntrza swoich programw.
Programowym ustawianiu i modyfikowaniu systemowych uprawnie Linuksa.
Monitorowaniu procesw w systemie.
Uyciu systemowego programu cron do ukadania harmonogramw zada
administracyjnych.
Implementowaniu wsplnych bibliotek obiektw.
Tworzenie moduw interfejsu Pascala dla istniejcych bibliotek jzyka C.
Tworzeniu wasnego systemu pomocy -- wcznie z wasn przegldark.
Rozwizywaniu codziennych programistycznych problemw w Kyliksie.
Co znajdziesz w tej ksice dla siebie:
Przegld systemu operacyjnego Linux, w porwnaniu z Windows.
Wprowadzenie do jzyka C dla programistw Pascala.
Przykady rozwiza rnorodnych programistycznych problemw Linuksa i Kyliksa,
wraz z omwieniami i przykadami kodu.
Ta ksika powstaa dla:
Programistw Delphi przenoszcych si do Kyliksa.
Programistw Visual Basica chccych przenie swoje programy do Linuksa.
Obecnych programistw Linuksa chccych tworzy aplikacje graficznego interfejsu
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
Spis treci
O Autorach .........................................................................................................11
Wprowadzenie .....................................................................................................13
Cz I
Okna w Linuksie.......................................................................................................................24
System X Window .................................................................................................................. 24
Meneder okien....................................................................................................................... 25
Cz II
Spis treci
Rozdzia 9. Szuflada............................................................................................269
9.1 Uzyskiwanie listy zalogowanych uytkownikw..............................................................270
Przykad: program LogUser.................................................................................................... 272
Spis treci
Skorowidz .........................................................................................................309
Rozdzia 4.
Podstawy C
dla programistw Kyliksa
Kluczowe zagadnienia:
Operatory jzyka C
Wskaniki
Funkcje i procedury
Elementy C++
Jak wspominalimy w rozdziale 2., Pascal nigdy nie by dla Linuksa gwnym jzykiem
programowania. Ogromna wikszo bibliotek zostaa napisana w C lub C++ i posiada interfejsy oraz przykadowy kod stworzone dla tych wanie jzykw. Istnieje bardzo niewiele
bibliotek stworzonych w Pascalu, a te, ktre powstay, s tak zalene od kompilatora,
dla ktrego zostay napisane, e najprawdopodobniej nie bd nadaway si do uycia
w Kyliksie. Oznacza to, e ty, jako programista Kyliksa, musisz podj decyzj. Jeli nie
chcesz czeka, a kto inny napisze potrzebne ci moduy, moesz albo przepisa same biblioteki, albo stworzy dla nich biblioteki porednie, budujc wasny interfejs API. Jeli wybierzesz pierwsze rozwizanie, spotkamy si za kilka lat, gdy skoczysz projekt. Gdy wybierzesz drugie rozwizanie, bdziesz zadowolony, poniewa Kylix znacznie upraszcza
tworzenie moduw interfejsw umoliwiajcych aplikacjom dostp do bibliotek jzyka C.
Zauwa, e uylimy zwrotu znacznie upraszcza, co niekoniecznie oznacza, e jest to
atwe. W pewnych przypadkach nie jest to nawet moliwe, szczeglnie, jeli biblioteki
zostay napisane w C++ (z wykorzystaniem specyficznych waciwoci tego jzyka).
Mamy jednak powody sdzi, e z czasem ilo bibliotek zgodnych z Kyliksem bdzie
rosa i mamy szczer nadziej, e wkrtce ten rozdzia stanie si niepotrzebny.
65
66
Teraz jednak moe si okaza, e bdziesz musia czyta przykady kodu napisanego
w C co stanowi ekscytujce wyzwanie dla programisty Pascala. Jzyk C jest znacznie bardziej zagmatwany ni Pascal i z tego powodu czasem moe przypomina szyfr.
Oglne zrozumienie niektrych struktur tego jzyka pomoe Ci jednak w zrozumieniu
dokumentacji interfejsw API i przykadw kodu stworzonych dla tego jzyka.
W tym rozdziale zaprezentujemy kluczowe informacje potrzebne do zrozumienia interfejsw i przykadw kodu, a take zademonstrujemy, w jaki sposb moesz stworzy
moduy interfejsw Pascala dla bibliotek C. Nie martw si nie bdziemy prbowali
zrobi z Ciebie programisty C. Jeli znasz ju ten jzyk, moesz przej bezporednio
do podrozdziau Wykorzystywanie bibliotek C w Kyliksie.
Typ Pascala
Opis
Zakres
128..127
32 768..32 767
lub
0..255
0..65535
lub
Brak
66
67
Tak jak w przypadku wszystkich typw w C, wskaniki mona tworzy dla kadego z typw cakowitych. Omwimy je nieco pniej. W przeszoci pojawia si powany problem
z typami rzeczywistymi (czyli zmiennoprzecinkowymi), poniewa ich implementacja
zmieniaa si zalenie od kompilatora. Oznaczao to, e typy i
nie byy
przenaszalne, zwaszcza pomidzy rnymi jzykami. Obecnie jednak wikszo kompilatorw przestrzega standardu IEEE (dla wymaga pojedynczej i podwjnej precyzji),
co znacznie zwiksza przenoszalno tych typw. Ale nawet mimo tego, jeli twoja
aplikacja korzysta z tych typw odwoujc si do bibliotek C, pamitaj, aby dokadnie
sprawdzi wyniki (patrz tabela 4.2).
Tabela 4.2. Porwnywalne rzeczywiste typy danych
Typ C
Typ Pascala
Opis
Zakres
Liczba zmiennoprzecinkowa
o pojedynczej precyzji
W przyblieniu od 3.4E38
do 3.4E+38
Liczba zmiennoprzecinkowa
o podwjnej precyzji
W przyblieniu od 1.7E308
do 1.7E+308
Liczba zmiennoprzecinkowa
o potrjnej precyzji
Rny
Typ Pascala
Opis
Typ wyliczeniowy
"
Wskanik
67
68
)*+
Utworzono tu nowy typ o nazwie . Zmiennym tego typu mona przypisywa
jedn z trzech wymienionych na licie wyliczenia wartoci, tak jak w:
#
&%
+
Tworzymy zmienn typu i ustawiamy jej warto jako sta symboliczn
. Jest to bardzo podobne (cho nie zamienne) do typu wyliczeniowego w Pascalu; zblionym odpowiednikiem powyszej deklaracji w Pascalu mogoby by:
%
#
&,%
)%
)-+
Wersja w jzyku C dziaa nieco inaczej, gdy wartoci staych symbolicznych na licie
mog by okrelone albo nieokrelone s wtedy numerowane kolejno poczwszy od
zera. Z perspektywy Pascala poprzednia deklaracja C tworzy zmienn o rozmiarze typu
i ustawia jej warto na 1.
W jzyku C nie ma jawnego typu . Zamiast niego warto logiczna jest symbolizowana przez kade wyraenie, dajce warto cakowit. Logiczny fasz odpowiada
wartoci zero, podczas gdy kada warto niezerowa odpowiada logicznej prawdzie. Gdy
musisz przekaza warto logiczn do funkcji API jzyka C, po prostu podaj warto
cakowit o odpowiedniej wielkoci, ustawion jako 0 dla faszu lub jako 1 dla prawdy.
acuchy istniejce w Pascalu nie posiadaj swojego odpowiednika w C. Zamiast tego
uywa on tablic znakw, zakoczonych znakiem pojedynczym o wartoci zero (znakiem null). Ten format nazywany jest formatem zakoczonym zerem lub acuchem
ASCIIZ. acuchy C s przekazywane jako wskaniki do znakw ( w C),
ktre w Pascalu mona przedstawi jako typ .
Dla wasnej wygody Kylix automatycznie umieszcza bajt o wartoci zero na ko5cu
dugich i szerokich a5cuchw. Uatwia to odwoywanie si* do nich jako do a5cuchw
zako5czonych zerem, gdy wystarczy po prostu zastosowa rzutowanie do typu .
68
69
$
. +
%+
.
/+
*+
%&
01
+
1
+
/1 +
+
Sowo kluczowe
suy w C do tworzenia nowego typu (w tym przypadku typu
o nazwie ), ktry moe by uywany tak jak kady oficjalny typ jzyka. Bez uycia sowa kluczowego typedef zmienne trzeba definiowa przy uyciu sowa kluczowego
, tak jak pokazano poniej:
. +
Jeli do stworzenia nowego typu zostao uyte sowo kluczowe
, sowo kluczowe moe zosta pominite.
Unia () w jzyku C podobna jest do posiadajcego warianty rekordu Pascala. Stanowi grup zmiennych zajmujcych w pamici to samo miejsce. Oto przykad unii w C
i odpowiadajcego jej w Pascalu rekordu z wariantami:
%
$
."+
2.3)2.(+
.3).().4).5+
*6
.54+
%6
.54&
"541,6
71
-+
"(1,3)(1 -+
"81,3)()4)51-+
+
W obu przykadach pola o rozmiarze bajtu zajmuj w pamici tyle samo miejsca, co pole
4-bajtowe. W rzeczywistoci w jzyku C korzysta si z tej moliwoci dosy czsto,
szczeglnie, gdy potrzebny jest dostp do poszczeglnych bajtw zmiennej.
69
70
Jeli musisz stworzy rekord odpowiadajcy okrelonej strukturze lub unii jzyka C,
zwr szczegln uwag na rozmiary poszczeglnych pl skadajcych si na niego
i uyj waciwych typw Pascala odpowiadajcych typom jzyka C. Musz one pasowa do siebie i musz zosta podane w tej samej kolejnoci, w przeciwnym razie pojawi si bdy danych.
Operatory jzyka C
C posiada wicej operatorw ni mgby przypuszcza. Czsto irytuje to programistw
Pascala. Operatory te znajdziesz w przykadach kodu, a cho wikszo z nich posiada
swj odpowiednik w Pascalu, istniej operatory specyficzne wycznie dla jzyka C (na
szczcie, mona znale sposb na obejcie wikszoci z takich operatorw).
Tabela 4.4 przedstawia operatory, ktre speniaj w C i w Pascalu podobne funkcje.
Podstawowe operatory matematyczne s w Pascalu przecione, mog wic by uywane take jako operatory dla acuchw. Taka sytuacja nie zdarza si w jzyku C, w ktrym
nie ma ustawionych typw, a do manipulowania acuchami uywa si funkcji. Operatory porwna numerycznych (na przykad , !, " oraz !") s jednak identyczne z odpowiednimi operatorami Pascala.
Jak wida, wiele operatorw jest do siebie podobnych, ale posiada inn symbolik. Kilka operatorw stosowanych jest w inny sposb na przykad, unarny operator wyuskania wskanika jest stosowany w C po lewej stronie operanda, podczas gdy w Pascalu
znajduje si po prawej stronie. Niektre operatory maj inne znaczenie, ale dziaaj podobnie. Istniej jednak operatory, ktre s unikalne dla jzyka C. S to: trjargumentowy operator warunkowy, operatory inkrementacji i dekrementacji, operatory przypisa
arytmetycznych, operator uzupenienia do jednoci oraz operator przecinka.
Pierwszy operand w tym operatorze warunkowym jest dowolnym wyraeniem zwracajcym warto logiczn (pamitaj, e w C wartoci logiczn jest kada warto cakowita
traktowana jako warto zerowa lub niezerowa). W tym przypadku wyraeniem tym
jest ""%. Drugim operandem jest warto, ktra zostanie zwrcona przez operator
w przypadku prawdziwoci wyraenia, za trzecim operandem jest warto, ktra zostanie
zwrcona w przeciwnym razie. W Pascalu ten przykad mona przepisa nastpujco:
&3
1&;
;
1&;;+
Uycie trjargumentowego operatora warunkowego nie jest zbyt czste, gdy sprawia
on, e kod programu staje si trudniejszy do przegldania.
70
71
Operator Pascala
<
<
'
'
Mnoenie liczb.
" oraz =
>
Dzielenie modulo.
?
'
'
&
Przypisanie.
1&
&&
Sprawdzenie rwnoci.
&
@@
A
BB
C
0
EE oraz FF
Bitowy AND.
A
Bitowy OR.
C
Bitowy XOR.
G
'F
I lub !I
J,-
JC,-
,E%F-
&(3+
&<<+
J&<<+
Na kocu tego przykadu zmienna foo jak moglimy oczekiwa, przyjmuje warto 12.
Prawdopodobnie podejrzewasz take, e zmienna przyjmuje warto 11, gdy && jest
obliczane jako warto operanda po dokonaniu inkrementacji operator jest umieszczony
71
72
Jak wida, operatory te s jedynie skrtem zapisu, ale prawie kady programista C powie Ci, e krtki zapis to dobry zapis.
72
73
Operator przecinka
Skrtowo zapisu, o ktrej wspominalimy wczeniej, moe czasem przybiera dziwne
formy. W jzyku C zdarzaj si sytuacje, w ktrych programista chce, by kilka instrukcji zostao wykonanych kolejno, pragnc jednoczenie, by syntaktycznie pozostay one
wyraeniem pojedynczym (zdarza si to czsto w ptlach , ktre omwimy ju
wkrtce). Operator przecinka jest po prostu przecinkiem umieszczanym pomidzy instrukcjami we wspomnianym wyej celu. Rezultatem powyszej operacji jest wyraenie
skadajce si z kilku instrukcji, ktre zwraca warto instrukcji znajdujcej si po
ostatnim przecinku. Pascal nie posiada odpowiednika tego operatora, lecz nie stanowi to
problemu, gdy w rzeczywistoci w Pascalu nie jest on potrzebny. Natrafienie na instrukcje oddzielone przecinkiem moe jednak sprawia kopot programistom Pascala, ktrzy
przyzwyczaili si do oddzielania instrukcji rednikami. Przykad uycia operatora przecinka pokaemy nieco dalej, w podrozdziale powiconym zastosowaniu instrukcji
w jzyku C.
Istniej (i s do czsto stosowane) take inne formy. Dziki nim ptle mog by konstruowane w bardzo elastyczny sposb, czasem nawet kosztem wikszej ich zoonoci
i zmniejszonej czytelnoci.
73
74
Ptla
,+ jzyka C jest bardzo podobna do ptli , Pascala, z tym e
ptla w C jest wykonywana, dopki warunek jest speniony (wyraenie ma warto rn od zera), za w Pascalu ptla jest powtarzana do chwili spenienia warunku (ma
warto true).
Ptle for
Ptla moe by uwaana za kolejny stosowany w jzyku C zapis skrtowy. Ptla
(lub bardziej poprawnie, instrukcja ) jest bardzo elastyczna i wydajna, ale moe
by rwnie bardzo zoona. Jej koncepcja przypomina nieco ptl w Pascalu, gdy
tu take nastpuje inicjalizacja licznika ptli i aktualizowanie go podczas kadego jej
przebiegu. Podstawowa forma tej instrukcji w jzyku C jest nastpujca:
,2T (+2T 4+2T 5
/S+
Instrukcja tworzy ciao ptli i wykonywana jest zero lub wicej razy, w zalenoci od
trzech zawartych w nawiasach wyrae. Pierwsze wyraenie jest wyraeniem inicjalizacyjnym. Jest obliczane raz (na pocztku instrukcji ) i zwykle suy do inicjalizowania
jednej lub wicej zmiennych licznika ptli. Drugie wyraenie jest podobne do wyraenia warunkowego wystpujcego w ptli +. Wyraenie to jest obliczane przy kadym wejciu do ptli. Ptla koczy dziaanie w chwili, gdy wartoci osigan przez to
wyraenie jest zero (lub gdy nakaemy wczeniejsze opuszczenie ptli). Ostatnie z wyrae jest wyraeniem modyfikujcym. Obliczane jest po kadej iteracji ptli i suy
zwykle do inkrementacji zmiennej licznika ptli.
Oto przykad ptli :
,&3+E(3+<<% ,:>:)-+
W instrukcji for mona jednak stosowa take kilka innych rozwiza. Kade z wyrae
w nawiasach jest opcjonalne. Innymi sowy, mona zastpi je instrukcj pust skadajc
si wycznie ze rednika. Ponisza instrukcja jest jak najbardziej poprawna (cho nie
jest zbyt uyteczna, gdy powoduje niekoczce si wykonywanie bezuytecznej ptli):
,++-+
74
75
Cho kod ten nie zdobyby nagrody za czytelno, zapisana w nim instrukcja jest poprawn
instrukcj jzyka C. (Jeli nie moesz zorientowa si, do czego ona suy, wyjaniamy,
e po prostu usuwa spacje z acucha znakw o nazwie ). Niestety, niektrzy programici C niektrzy, nie wszyscy zdaj si przyjmowa instrukcje takie jak ta za
moliwy do przyjcia kod, co sprawia, e czytanie przykadowych programw staje si
bardzo trudne. (Syszaem kiedy tak krytyczn uwag na temat jzyka C: Musi by
co nie tak z jzykiem, ktry atwo pozwala na wskazanie instrukcji i stwierdzenie
Zao si e zgadniesz do czego suy ta linia kodu.)
Wskaniki
Cho Pascal obsuguje wskaniki, jednak jego programici nie wykorzystuj ich tak czsto jak programici C. W jzyku C wskaniki stanowi podstawowy element programu,
s uywane wszdzie i rozumiane przez wszystkich. (Lub prawie wszystkich nawet
zatwardziali programici C maj z nimi czasem problemy.)
Wskanik (ang. pointer) jest adresem okrelonego miejsca znajdujcego si w pamici.
Wskaniki umoliwiaj programistom przekazywanie parametrw przez referencj (co
omwimy wkrtce), prac z dynamicznie alokowan pamici oraz efektywne reprezentowanie zoonych struktur danych. Wskaniki cile wi si te z tablicami.
Spjrzmy na przykad w jzyku C:
&43+
%+
75
76
wskanika najprawdopodobniej doprowadziaby do zniszczenia programu. Aby wskanik wskazywa na zmienn
-, konieczne jest uycie poniszej instrukcji:
%&@+
Na szczegln uwag zasuguj dwie linie. Pierwsza z nich to ta, w ktrej deklarowana
jest zmienna . Zwr uwag, e zmiennej , wskanikowi do wartoci typu ,
przypisywana jest zmienna / bdca odniesieniem do tablicy wartoci typu .
Wszystkie tablice w jzyku C mog by przekazywane jako wskaniki w wyniku zwyczajnego pominicia operacji indeksowania. W tym przypadku tablica / (sama,
bez indeksu) stanowi odpowiednik wskanika do typu , co umoliwia wykonanie tego przypisania. Najczciej spotkasz si z tym przy okazji uycia w jzyku C tablic
znakw symbolizujcych acuchy. Tablice te bd przekazywane zwykle przy uyciu
bazowej nazwy tablicy jako typu .
Drug wart uwagi lini jest ostatnia linia przykadu instrukcja &&. Efektem
dziaania tego wyraenia jest uzyskanie wyuskanej wartoci wskanika w celu wypisania jej na ekranie, a nastpnie inkrementacja samego wskanika. Inkrementacja wskanika dokonana w ten sposb powoduje, e jest on zwikszany o okrelon liczb bajtw,
zgodn z rozmiarem typu, na ktry wskazuje wskanik (ustalan przez kompilator). Przy
inkrementacji wskanikw, procedury oraz ( w Pascalu dziaaj w ten sam sposb. W wyniku przeprowadzenia tej operacji nie zostaa zmieniana adna pami (mimo
zmiany wygldu wyraenia). Gdyby chcia inkrementowa zawarto pamici wskazywanej przez ten wskanik, musiaby uy nastpujcego wyraenia:
,%-<<+
76
77
W ten sposb tworzymy nowy typ noszcy nazw nazwie 0
. Dwukrotne pojawienie
si nazwy typu, w pierwszej i ostatniej linii deklaracji, jest konieczne, aby umoliwi
zastosowanie deklaracji w linii czwartej. Jzyk C nie pozwala na uywanie referencji
wstpnych, wic typ Node nie mgby zosta uyty przed stworzeniem go w ostatniej linii.
Nastpnie tworzymy pierwszy wze listy poczonej, dynamicznie alokujc pami za
pomoc funkcji 12:
0
&,0-,
J,0--+
'F. &::+
'F &0M+
Zwr uwag na zastosowanie rzutowania w celu konwersji wskanika do /
(zwracanego przez funkcj 12) na wskanik do typu 0
, a take na uycie operatora
)12 w celu okrelenia iloci bajtw, ktra powinna zosta zaalokowana. Zwr
take uwag na uycie operatora wyboru pola struktury ('!, zwanego take operatorem
strzaki) przy odwoywaniu si do pl w nowo zaalokowanej strukturze 0
, a take na
zastosowanie wartoci 033 do zainicjalizowania wskanika do nieistniejcego nastpnego wza listy. Warto 033 w jzyku C stanowi odpowiednik wartoci w Pascalu.
Na zakoczenie tworzymy nastpny element listy i ustawiamy pierwszy element tak aby
na niego wskazywa:
0%&,0-,
J,0--+
%'F. &:%
:+
%'F &0M+
'F &%+
Teraz przejcie przez elementy listy sprowadza si ju tylko do uycia poniszej ptli:
,%&
+%D&0M+%&%'F $
% ,:>
Y :)%'F. -+
*
77
78
Podobnie jak Pascal, jzyk C obsuguje take wskaniki do funkcji. Jednak o ile w Pascalu sposb deklaracji tego typu wskanika jest bardzo prosty, w jzyku C moe on by
bardzo trudny do odszyfrowania. Oto przykad deklaracji w Pascalu, w ktrej tworzymy
nowy typ o nazwie 4, bdcy wskanikiem do funkcji zwracajcej warto
cakowit i otrzymujcej jako parametr pojedyncz warto cakowit.
#%
L &L ,S1
-1
+
Jeli sygnatury funkcji nie s skomplikowane, cao nie jest zbyt trudna do odczytania.
Jednak gdy staj si one bardziej zoone, wskaniki do funkcji s jednymi z najtrudniejszych fragmentw kodu w jzyku C. Nawet dowiadczeni programici C musz
czasem si zatrzyma, wzi gboki oddech i powoli analizowa deklaracj wskanika
do tak zoonej funkcji.
Funkcje i procedury
Wiele konwencji deklarowania i wywoywania funkcji i procedur stosowanych w jzyku C oraz w Pascalu jest podobnych do siebie. Pod wzgldem skadni, funkcja w C nie
rni si od procedury, ktra w C jest po prostu funkcj zwracajc /
.
Wszystkie funkcje w C zdefiniowane jako zwracajce cokolwiek innego ni /
musz
posugiwa si instrukcj zwracajc warto do funkcji wywoujcej. Oto przykad:
"+
Podobnie jak w Pascalu, argumenty funkcji jzyka C mog by przekazywane przez dan warto lub przez odniesienie. Jednak w odrnieniu od Pascala, nie istniej w tym
jzyku adne specjalne sowa kluczowe (takie jak np. /) wskazujce, e argument
przekazywany jest przez odniesienie. Zamiast sw kluczowych uywa si tu wskanikw, tak jak w poniszym przykadzie:
78
79
"
L , " ) " $
" <<+
" <&(3+
*
Pozostae zagadnienia
W tym podrozdziale omwimy kilka rnic pomidzy jzykiem C a Pascalem, ktrych
dotd nie dao si nigdzie przyporzdkowa. Chodzi tu o indeksowanie tablic, dynamiczn alokacj pamici oraz preprocesor jzyka C.
Indeksy tablic
W Pascalu programici mog deklarowa swoje tablice wraz z indeksami obejmujcymi
dowolny zakres wartoci cakowitych. W C indeksy tablic obejmuj zawsze zakres od 0
do rozmiaru tablicy (minus jeden, bo indeks tablicy zaczyna si od zera). Na przykad,
w tej definicji tablicy:
"
V(3W+
Gdyby skadnia taka zostaa uyta w C, oznaczaaby to, e programista chce wykorzysta operator przecinka w sposb sprzeczny z reguami. W C odpowiednik tej instrukcji
wyglda nastpujco:
"&AVWVSW+
79
80
Oba przykady alokuj blok pamici w rozmiarze odpowiednim dla przechowania rekordu typu 5
.
Pascal korzysta w tym celu te z procedur 0+ oraz (. C nie posiada tego mechanizmu, za C++ dysponuje nim w formie operatorw + i
.
Preprocesor jzyka C
Temat ten moe atwo rozpta ma wojn, ale nie wolno go w tej ksice pomin.
Preprocesor jest bardzo uyteczn czci jzyka C, moe jednak doskonale gmatwa
czytelno kodu.
Preprocesor jzyka C jest mechanizmem przeznaczonym do podstawiania tekstu, uruchamianym w pierwszym przebiegu kompilatora C. Uywany jest do celw takich jak:
podstawianie zmiennych, internalizacja acuchw czy rozwijanie makr (cho z pewnoci istniej lepsze sposoby wykonania tych zada). Mechanizm podstawiania przyjmuje prost posta, co pokazuje poniszy przykad:
[ A\.0.\A65X
[ ? C\.0A?:]:
[ N.0.\A6A\.0.\A6=K
Preprocesor stworzy nastpujcy kod, ktry moe potem zosta skompilowany w tradycyjny sposb:
% ,:>
JS2%J )>J2/I:)
:]:)5X=K-+
,:S
/ SJS:-+
[
80
81
Powyszy fragment ma na celu wygenerowanie komunikatu debugowania, ktry zostanie skompilowany tylko wtedy, gdy zdefiniowane zostao makro (:6 preprocesora (na
przykad przy uyciu dyrektywy ;
). Naley pamita, e sprawdzanie odbywa si
podczas kompilacji, a nie podczas dziaania programu; jeli makro (:6 nie zostanie
zdefiniowane, instrukcja nie bdzie nawet wkompilowana do programu. Kylix posiada
identyczny mechanizm wykorzystujcy dyrektywy <=4(:4> oraz <=:0(4>.
Ten przykad zostanie rozszerzony tak, by zapewnia warunkow kompilacj kodu specyficznego dla okrelonej platformy. W zalenoci od aktualnie uywanej platformy definiowane bd rne makra, za w oparciu o ich definicje kompilowane bd rne
bloki kodu. Wyglda to nieadnie (zgadzaj si z tym nawet puryci jzyka C), ale jest
efektywne i duo atwiejsze ni zajmowanie si osobnymi dla kadej obsugiwanej platformy plikami rdowymi.
Ostatnim popularnym zastosowaniem preprocesora jest doczanie plikw rdowych.
Funkcja ta wykorzystywana jest w praktycznie kadym tworzonym kodzie rdowym C.
Bloki kodu C, zawierajce zwykle definicje makr, deklaracje typw oraz funkcji s zapisywane w tak zwanych plikach nagwkowych. Nazwy tych plikw zwykle posiadaj
rozszerzenie .h. Pliki nagwkowe odpowiadaj sekcjom interfejsw w plikach rdowych Pascala i mog by wykorzystywane przez rne pliki rdowe C poprzez zastosowanie dyrektywy ;
preprocesora. Dyrektywa ta przypomina instrukcj
Pascala wykonanie jej informuje kompilator o typach, metodach i staych zawartych
w doczanym pliku nagwkowym. Czsto uywan w C dyrektyw jest:
[ E
IF
Elementy C++
Cho jzyk C++ posiada w wikszoci tak sam skadni jak jzyk C, jednak dysponuje kilkoma dodatkowymi waciwociami, ktre mog stanowi dla Ciebie prawdziwe
wyzwanie. Niektre z tych waciwoci bardzo utrudniaj (a czasem wrcz uniemoliwiaj) uycie bibliotek napisanych specjalnie dla programw C++. Moglibymy napisa
ca ksik o rnicach pomidzy tymi dwoma jzykami, ale wykraczaaby ona daleko
poza temat poruszany w niniejszej ksice. Zamiast tego skupimy si na trzech rnicach, na ktre bdziesz natrafia najczciej prbujc wykorzysta biblioteki zewntrzne: funkcje przecione, funkcje skadowe oraz wyjtki.
81
82
Funkcje przeci()one
W jzyku C wszystkie funkcje musz posiada nazwy unikalne. Jednak w C++ dozwolone jest posiadanie dwch funkcji o identycznych nazwach, rnicych si jedynie listami
parametrw. Na przykad, ponisze dwie funkcje:
.", "-+
.","-+
spowoduj w C bd kompilatora, cho w C++ s jak najbardziej poprawne. Aby zapewni sobie dostp do tej nowej moliwoci i nadal mc korzysta ze starych narzdzi,
projektanci jzyka C++ wykorzystali sygnatur funkcji (ilo i typy parametrw) jako
nazw funkcji przechowywan w skompilowanym kodzie obiektu. W ten sposb istniejce linkery, debugery i inne narzdzia programistyczne mog by uywane nadal
mimo istnienia funkcji przecionych. Ten proces wczania sygnatury funkcji do skompilowanego kodu obiektu nazywany jest dekoracj nazw. Na przykad, nazwa funkcji:
#
L , ))J-+
Cho jest to niewtpliwie eleganckie rozwizanie problemu prezentacji funkcji przecionych w skompilowanym kodzie obiektu, powoduje jednak problemy, gdy prbuje si
uy tych funkcji w Kyliksie. Udekorowana nazwa funkcji nie wynika w sposb oczywisty z kodu, ale bez jej istnienia nie ma moliwoci poinformowania Kyliksa, ktrej
funkcji ze wsplnej biblioteki C++ chcesz w danej chwili uy.
Istnieje rozwizanie tego problemu, cho nie jest ono zbyt eleganckie. Gdy okrelisz ju
wspln bibliotek, ktrej chcesz uy, moesz przejrze za pomoc programu nm list
funkcji, ktre eksportuje. Program wypisuje list funkcji eksportowanych z pliku
obiektu lub ze wsplnej biblioteki. W przypadku biblioteki C++, nazwy te bd udekorowane. Do odzyskania nazwy udekorowanych funkcji suy program c++filt, dziki ktremu moesz uzyska udekorowan nazw dla kadej z nazw czytelnych. Jak to zrobi?
Po pierwsze, uruchom w linii polece program nm, przekazujc mu jako parametr nazw wsplnej biblioteki i przekieruj jego wyjcie do programu c++filt. Wynik zapisany
na ekranie bdzie wyglda podobnie do przedstawionego poniej:
>
I
I(B<<
33333333##
L , ))33333333
4.%I
Kolumna pierwsza (sekwencja cyfr) zawiera adres funkcji wewntrz wsplnej biblioteki, podczas gdy kolumna trzecia zawiera nazwy funkcji eksportowanych przez t bibliotek. Zwr uwag, e program c++filt zwraca czytelne nazwy funkcji. Moesz
uy tych pozbawionych dekoracji nazw do zlokalizowania funkcji, ktre chcesz wywoa w swoim kodzie. Nastpnie ponownie uruchom to samo polecenie, tym razem bez uycia filtra c++filt. Na ekranie zobaczysz ponisz list:
>
I
I(
33333333##
L ..L
33333333
4.%I
82
83
Odszukaj funkcj o tym samym adresie i uzyskasz w ten sposb udekorowan nazw,
ktr moesz wskaza w zewntrznej definicji w swoim interfejsie biblioteki.
Mwilimy, e nie jest to zbyt eleganckie wyjcie z sytuacji. W rzeczywistoci nie jest
take stuprocentowo pewne cakowicie zawodzi, gdy w bibliotece s uywane funkcje
skadowe (omwimy je za chwil). Ale moesz przynajmniej od czego zacz. Ta metoda, cho mudna, jest skuteczna w przypadku funkcji C++ nie bdcych funkcjami
skadowymi, szablonami funkcji oraz funkcjami nie zgaszajcymi wyjtkw.
Funkcje skadowe
W C++ funkcje skadowe (funkcje powizane z klas) musz przekazywa jako pierwszy parametr funkcji adres obiektu, dla ktrego zostay wywoane. Normalnie kompilator C++ dokonuje tego automatycznie w sposb niewidoczny dla programisty. Nie
uywasz jednak kompilatora C++ i nie znasz (nie moesz go nawet uzyska) adresu
obiektu C++. Dopki Borland nie wyda pakietu czcego Kylix z C++ Borlanda (podobnego do wersji dla Windows), funkcje skadowe C++ bd dla programistw Kyliksa
niedostpne.
Wyj(tki
Wyjtki w C++ s podobne do wyjtkw w Kyliksie: posiadaj wasna metod powiadomienia funkcji wywoujcej o bdach, ktre wystpiy podczas przetwarzania. Jednak
mechanizmy uywane przez C++ i Kylix z pewnoci nie bd ze sob zgodne. Take
w tym przypadku, o ile Borland nie wyda pakietu czcego C++ z Kyliksem, kada
funkcja C++ zadeklarowana jako zgaszajca wyjtki bdzie dla programistw Kyliksa
niedostpna.
83
84
ni pisanie interfejsu przedstawionego w tym rozdziale. Jednak samodzielne jego napisanie posuy jako przykad praktycznego wykorzystania zasad, ktre poznae w tym
rozdziale.
Pewna liczba bibliotek zewntrznych jest dystrybuowana jako biblioteki statyczne, do
ktrych Kylix nie ma dostpu. W przypadku takich bibliotek wymagane jest przekompilowanie kodu rdowego biblioteki tak, by powstaa wsplna biblioteka (co opisywalimy w rozdziale 3). W tym celu musisz wrci na jaki czas do linii polece i pozna podstawy plikw makefile. Jeli biblioteka zewntrzna jest ju bibliotek wspln,
moesz ten krok pomin (i by z tego bardzo zadowolony).
Ten minimalny plik ustanawia kilka regu, ktre zostan uyte przez program make do
stworzenia pliku wykonywalnego o nazwie hello. Pierwsza linia okrela zalenoci: plik
hello (zwany celem) jest zaleny od pliku hello.c. Gdy zostanie uruchomiony program
make, sprawdzi, czy plik hello.c zosta zmodyfikowany pniej ni plik hello. Jeli plik
hello.c nie zosta zmodyfikowany, program make zakoczy dziaanie. Jeli jednak plik
rdowy uleg modyfikacji, wykonane zostanie polecenie zawarte w nastpnej linii, co
spowoduje, e cel zostanie zaktualizowany zgodnie z plikami umieszczonymi na licie
zalenoci. Dla reguy pojedynczej moe pojawi si kilka plikw zalenoci, za lista
polece moe przyj dugo potrzebn. Polecenia, ktre s zbyt dugie, mona podzieli na kilka linii, umieszczajc na kocu kadej z nich znak lewego ukonika (?).
Innym elementem, ktry powiniene lepiej pozna, s zmienne plikw makefile. Zmienne te s uywane w wikszoci plikw makefile w celu uatwienia modyfikacji i zrozumienia skomplikowanych regu. Nam mog posuy do uatwienia aktualizacji pliku makefile tak, by stworzy wspln bibliotek.
Zmienne definiowane s przy uyciu standardowo okrelonego przypisania, na przykad
takiego jak to:
LAZ&'
84
85
Ta zmienna moe zosta teraz uyta w dowolnym miejscu pliku makefile z wykorzystaniem zapisu =143862, ktry podczas dziaania programu make zostanie zastpiony zawartoci zmiennej. Moesz rozszerzy minimalny plik makefile uywajc zmiennych
(jak pokazuje poniszy przykad):
LAZ&'
A 0A?&
6L&I
R,A 0A?-1R,6L
R,LAZ-^R,A
0A?-R,6L-
Gdy wywoamy dla tego pliku makefile program make, otrzymamy wynik dokadnie taki sam jak w przypadku pliku minimalnego. (Cho w tym przykadzie nie dokonalimy
niczego nowego, poznae zasady, ktre przydadz si w trakcie modyfikacji pliku makefile w celu stworzenia wsplnej biblioteki.)
Aby uatwi sobie zarzdzanie przykadem, stworzylimy szkielet pliku makefile dostarczanego wraz z kodem rdowym biblioteki Blowfish. Listing 4.1 zawiera plik makefile,
ktry zostanie zmodyfikowany w celu stworzenia wsplnej biblioteki.
Listing 4.1. Szkieletowy plik makefile
&
LAZ&'
A6&
6A0&
&%I
C]&.
/I.I. I.I.I
1R,C]R,A6-R,-R,C]R,6A0-R,-
Zmodyfikowanie pliku makefile tak, by tworzy wspln bibliotek, jest do atwe. Jeli nie odwiedzie podanego pod koniec trzeciego rozdziau adresu URL, moesz uczyni to teraz i zajrze do podrozdziaw Creating a shared library oraz Installing and using
a shared library, znajdujcych si w tym dokumencie. Dziki zapoznaniu si z nimi atwiej
zrozumiesz co robimy.
Aby stworzy wspln bibliotek, kompilator C musi zosta uruchomiony wraz z opcj
@ (dodan do innych uywanych ju opcji) w celu stworzenia kodu zalenego od
pozycji. Wystarczy wic doda t opcj do linii definiujcej zmienn 4386, spowoduje
to, e opcja @ zostanie uyta wszdzie tam, gdzie w pliku makefile zostaa zastosowana ta zmienna:
LAZ&'
^
Aby utworzy wspln bibliotek, musimy wykona jeszcze jedno zadanie zebra
skompilowane pliki obiektw w pliku .so. Tene plik makefile wykorzystuje do stworzenia statycznej biblioteki aplikacje ar oraz ranlib. My zastpimy je poleceniami wymaganymi do stworzenia biblioteki wsplnej:
85
86
Aby dowiedzie si, do czego su te polecenia, zajrzyj pod adres URL podany na
kocu rozdziau trzeciego. Dokument ten przedstawia take sposb instalowania nowootrzymanej biblioteki wsplnej, nie bdziemy wic omawia go w ksice. Ostateczna
posta pliku makefile zostaa przedstawiona na listingu 4.2.
Listing 4.2. Plik makefile uywany do stworzenia biblioteki wsplnej Blowfish
&
LAZ&'
'
A6&
6A0&
&%I
C]&.
/I.I. I.I.I
1R,C]R,-'
'()'
)2
I
I(Y
'2
I
I(I3I(R,C]-^
86
87
%
\
;
)
%
"I
%/
%)\
"
%
I
#
%
%
, -%"2%/
I
6
)22
)%%"2
1
(I6
%
)
2
I
4I6
%"%
)
2
=
%"2
I
5IA"
2
%2
/ 2
1
:#
%
%
%
22
\
,H%
I-:
#2;%
%;
%
%1'-I
I 2
%,""-
%%
,%% -
/ 2
1
:#
%
22 #_
,SH%
I-:
#_CL#A6 6C7\6\CM0Z;;A;;A0
A0\G 6C6? A66A0#)0M0Z)M#0C#?##C)#_
? A66A0#CL?6_A0#A#\A0L#0LC6A A6#MA6 M6 C
A6A?I00C70#_A#_AM#_C6C6C0#6M#C6A
LC6A0\6#)06#)00#A) A)G? A6\)C6C0`M0#A
A?AZ,0M0Z)M#0C#?##C) 6CM6?0#CLM##M#ZCC
C667+CCLM)A#A)C6 6CL#+C6M00#66M #C0_C76AMA0C0A0\#_C6\CLA#\)_#_60C0#6A#)#6#
A#\)C6#C6#,0M0Z0ZZ0C6C#_6-A60Z0A0\A\
CM#CL#_MCL#_CL#A6)70LA7CL#_ C#\CL
M_A?AZI
#
%""
""
III
%
% %
V
Z0M IW
=
[ _A6.CL_._
[ _A6.CL_._
[..%
%
::$
[
[ L.06\ #(
[ L.6\ #3
=/
;
;% "
22/
A%)2
2 I
;8;
L.C0Z ; '% ; %
A%=
[ L.C0Z
87
88
*
[
[
88
89
Nastpna linia zawiera kolejn czsto wystpujc w plikach nagwkowych konstrukcj. Makro preprocesora zostao zdefiniowane tylko w kompilatorach C++
i zastosowano tu je w celu poinformowania kompilatora C++, e wszystko, co zostao
zdefiniowane w tym pliku, korzysta z konwencji nazw jzyka C, a nie C++. Zabezpiecza to kompilator C++ przed generowaniem odwoa do zewntrznych funkcji noszcych udekorowane nazwy. W naszym przypadku rwnie moesz to zignorowa, zwracajc uwag tylko na to, e operujesz bibliotek eksportujc standardowe nazwy C
(a nie udekorowane nazwy C++).
Nastpne linie deklaruj dwie stae: 4:059 oraz 4(:59. Symbole te podporzdkowane s funkcjom wywoujcym, stworzymy wic par wasnych odpowiadajcych im staych. Stae te bd uywane do przekazywania parametrw o nazwie ,
okrelonych w deklaracjach procedur:
#%
L.06\ #&(+
L.6\ #&3+
Nastpne linie definiuj inne makro preprocesora, noszce nazw 43A06, ktre w pliku rdowym zostanie zastpione typem
. Typ danych nazywanych '
odpowiada typowi 3B
Kyliksa. Masz w tej sytuacji do wyboru dwie
moliwoci: moesz zapamita, e 43A06 i 3B
s synonimami i samodzielnie
dokona podstawienia, lub zadeklarowa nowy typ i uy go w module interfejsu. Obydwa te rozwizania s skuteczne, ale zdefiniowanie wasnego typu znacznie uatwia
pniejsze przenoszenie kodu. Zadeklarujemy wic nowy typ, nadajc mu nazw 43A06:
#%
L.C0Z&
+
Dwie nastpne linie deklaruj stae, ktre bd uywane w bibliotece i ktrych potrzebujemy do poprawnego okrelenia rozmiarw pewnych pl danych. Moesz po prostu
doda je do rozpocztej wczeniej sekcji :
L.6CM0&(+
L.CN&8+
Nastpnie musimy przetumaczy struktur wymagan przez bibliotek. Mamy ju zdefiniowany typ (43A06), dziki ktremu struktura ta jest stosunkowo atwa do odtworzenia. Poniewa staa 4x256 nigdy si nie zmienia, moemy zamiast niej podstawi
sta 1 024. Moemy take stworzy nowy typ wskanikowy, ktry nieco uatwi nam
korzystanie z tej struktury w deklaracjach funkcji:
#%
L.N\&6
1AV(IIL.6CM0<4WL.C0Z+
1AV(II(34WL.C0Z+
+
L.N\&!L.N\+
89
90
posiada identyczne nazwy funkcji. Pierwszy blok zawiera pene deklaracje list parametrw funkcji, podczas gdy blok drugi zawiera jedynie ich nazwy. W starszym kodzie C (tak
zwanym K&R C, skrcie pochodzcym od nazwisk twrcw jzyka) deklaracje funkcji
nie zawieray list parametrw. Z czasem jednak okazao si, jak wane s pene deklaracje funkcji (zwane take prototypami funkcji). Jednak sporo bibliotek zawiera deklaracje
funkcji bez list parametrw (w celu zachowania zgodnoci ze starszymi kompilatorami).
W tym pliku nagwkowym programista uy kompilacji warunkowej opartej na makro
0A5AA. Jeli makro to jest niezdefiniowane, kompilator uyje penych prototypw
funkcji z bloku pierwszego. Jeli jest zdefiniowane, kompilator uyje tylko nazw procedur zawartych w bloku drugim. Poniewa Kylix obsuguje pene prototypy funkcji, moemy zupenie zignorowa blok drugi.
Aby mc przetumaczy deklaracje metod, musimy przetumaczy zarwno typ zwracany, jak i list parametrw metody. W przypadku tej biblioteki przetumaczenie typw zwracanych jest atwe, gdy typ inny ni void zwraca tylko jedna funkcja. Funkcjom C zwracajcym w Pascalu /
odpowiadaj procedury. Aby przetumaczy listy parametrw,
uyj tabel 4.1, 4.2 oraz 4.3. Wyszukaj typ Pascala dokadnie odpowiadajcy odpowiedniemu typowi jzyka C i stwrz deklaracj parametru. Przyjrzyjmy si bliej pierwszej
z funkcji.
Pierwsza funkcja, 4., posiada trzy parametry. Pierwszym z nich jest wskanik
do struktury 4C:9. Gdy przekazujesz go do funkcji, moesz zaoy, e funkcja modyfikuje zawarto wskazywanej przez niego struktury (tak te stao si w naszym przypadku). Ten parametr zostanie zadeklarowany jako wskanik do struktury 4C:9, tak
jak w deklaracji funkcji w C. Moesz uy typu wskanikowego, ktry wczeniej przewidujco zadeklarowalimy dla typu rekordu:
L.
./,/1 L.N\+III
Drugi parametr zaliczamy do typu . Jak pamitasz, rozmiar tego typu zaley od
kompilatora C uytego do skompilowania biblioteki. W wikszoci platform (wcznie
z Linuksem) jest to warto 32-bitowa (ale powiniene si o tym upewni). W tej deklaracji moesz uy typu 3:
L.
./,/1 L.N\+ 1
+III
Ostatnim parametrem jest wskanik do zmiennej typu
. Ten typ deklaracji
jest uywany czsto jako wskanik do wystpujcego w pamici obszaru pozbawionego
typu, szczeglnie, gdy wystpuje razem z parametrem okrelajcym dugo (ang.
length), tak jak w tym przypadku. Aby uatwi sobie uycie tego parametru w ten wanie sposb, moesz do jego reprezentacji uy oglnego typu wskanikowego:
L.
./,/1 L.N\+ 1
+1 -+
90
91
Jestemy wic coraz bliej. Pozostao nam ju tylko dostarczenie w sekcji implementacji
definicji dla funkcji i procedur zadeklarowanych w sekcji interfejsu. W tym celu moesz uy definicji zewntrznych, wskazujc kompilatorowi wspln bibliotek zawierajc implementacje tych metod. Aby to uczyni w sposb uporzdkowany, wr do
sekcji staych i dodaj do nich now sta reprezentujc nazw pliku .so. Nastpnie uyj
tej staej w definicjach zewntrznych:
L&;I
I(;+
Efektem dziaania tej linii jest poinformowanie kompilatora, aby wygenerowa kod
dziaania szukajcy (funkcjonujcy podczas dziaania programu) pliku libbf.so.1 i aby
uy implementacji funkcji 4. dziaajcej w tym pliku jako funkcji wywoywanej we wszystkich miejscach wystpie w plikach rdowych funkcji o tej nazwie.
Pena, kocowa posta moduu interfejsu zostaa przedstawiona na listingu 4.4. Po
skompilowaniu, modu ten moe zosta uyty dokadnie tak samo jak inne moduy Kyliksa. Po prostu docz jego nazw (+) do klauzuli znajdujcej si w pliku
rdowym chccym korzysta z biblioteki Blowfish.
91
92
Listing 4.4. Blowfish.pas, peny modu interfejsu dla zewntrznej biblioteki Blowfish
2
+
L.06\ #&(+
L.6\ #&3+
L.6CM0&(+
L.CN&8+
L&;2
I
I(;+
#%
L.C0Z&
+
L.N\&6
1AV(IIL.6CM0<4WL.C0Z+
1AV(II(34WL.C0Z+
+
L.N\&!L.N\+
L.
./,/1 L.N\+ 1
+1 -++
L.. %, %1 +1 +
/1 L.N\+ 1
-++
L.. %, %1 +1 +
1
+
/
1 L.N\+"1 + 1
-++
L.. %, %1 +1 +
1
+
1 L.N\+"1 +
1
+ 1
-++
L.. %, %1 +1 +
1
+
1 L.N\+"1 +
1
-++
L L.%
1 ++
%
%L.
./+ L ;L.
./;+
%L.. %+ L ;L.. %;+
%L.. %+ L ;L.. %;+
%L.. %+ L ;L.. %;+
%L.. %+ L ;L.. %;+
L.%
+ L ;L.%
;+
I
92
93
93