Użyj polecenia ar Linuksa, aby utworzyć biblioteki funkcji podczas tworzenia oprogramowania. Ten samouczek pokaże, jak utworzyć bibliotekę statyczną, zmodyfikować ją i użyć w programie, wraz z przykładowym kodem.
Polecenie ar to prawdziwy weteran – istnieje od 1971 roku. Nazwa ar nawiązuje do pierwotnego zamierzonego zastosowania narzędzia, którym było do tworzenia plików archiwalnych. Plik archiwum to pojedynczy plik, który działa jako kontener dla innych plików. Czasami dla wielu innych plików. Pliki można dodawać, usuwać lub wyodrębniać z archiwum. Osoby szukające tego typu funkcjonalności nie zwracają się już ku ar. Rola ta została przejęta przez inne narzędzia, takie jak tar.
Jednak polecenie ar jest nadal używane do kilku celów specjalistycznych. ar służy do tworzenia bibliotek statycznych. Są one używane w tworzeniu oprogramowania. Ar jest również używany do tworzenia plików pakietów, takich jak „.deb” używanych w dystrybucji Debian Linux i jego pochodnych, takich jak Ubuntu.
Przeprowadzimy kroki wymagane do utworzenia i zmodyfikowania biblioteki statycznej oraz zademonstrujemy, jak używać tej biblioteki w programie. Aby to zrobić, potrzebujemy wymagania, aby biblioteka statyczna spełniała. Celem tej biblioteki jest kodowanie ciągów tekstu i dekodowanie zakodowanego tekstu.
Należy pamiętać, że jest to szybki i brudny hack do celów demonstracyjnych. Nie używaj tego szyfrowania do niczego, co ma wartość. To najprostszy na świecie szyfr podstawieniowy, gdzie A staje się B, B staje się C i tak dalej.
Funkcje cipher_encode () i cipher_decode ()
Będziemy pracować w katalogu o nazwie „biblioteka”, a później utworzymy podkatalog o nazwie „test”.
W tym katalogu mamy dwa pliki. W pliku tekstowym o nazwie cipher_encode.c mamy funkcję cipher_encode ():
void cipher_encode(char *text) { for (int i=0; text[i] != 0x0; i++) { text[i]++; } } // end of cipher_encode
Odpowiednia funkcja cipher_decode () znajduje się w pliku tekstowym o nazwie cipher_decode.c:
void cipher_decode(char *text) { for (int i=0; text[i] != 0x0; i++) { text[i]--; } } // end of cipher_decode
Pliki zawierające instrukcje programowe nazywane są plikami kodu źródłowego. Zamierzamy utworzyć plik biblioteki o nazwie libcipher.a. Będzie zawierał skompilowane wersje tych dwóch plików z kodem źródłowym. Stworzymy również krótki plik tekstowy o nazwie libcipher.h. To jest plik nagłówkowy zawierający definicje dwóch funkcji w naszej nowej bibliotece.
Każdy, kto ma bibliotekę i plik nagłówkowy, będzie mógł używać tych dwóch funkcji we własnych programach. Nie muszą ponownie wymyślać koła i ponownie pisać funkcji; po prostu korzystają z kopii w naszej bibliotece.
Kompilowanie plików cipher_encode.c i cipher_decode.c
Aby skompilować pliki z kodem źródłowym, użyjemy gcc, the standardowy kompilator GNU. Opcja -c (kompilacja, brak łącza) nakazuje gcc skompilować pliki, a następnie zatrzymać. Tworzy plik pośredni z każdego pliku kodu źródłowego zwanego plikiem obiektowym. Konsolidator gcc zwykle pobiera wszystkie pliki obiektowe i łączy je ze sobą, tworząc program wykonywalny. Pomijamy ten krok, używając opcji -c. Potrzebujemy tylko plików obiektowych.
Sprawdźmy, czy mamy pliki, które naszym zdaniem mamy.
ls -l
W tym katalogu znajdują się dwa pliki kodu źródłowego. Użyjmy gcc, aby skompilować je do plików obiektowych.
gcc -c cipher_encode.c
gcc -c cipher_decode.c
Jeśli wszystko pójdzie dobrze, gcc nie powinno wychodzić.
Spowoduje to wygenerowanie dwóch plików obiektowych o tej samej nazwie co pliki kodu źródłowego, ale z rozszerzeniami „.o”. To są pliki, które musimy dodać do pliku biblioteki.
ls -l
Tworzenie biblioteki libcipher.a
Aby utworzyć plik biblioteki – który w rzeczywistości jest plikiem archiwum – użyjemy ar.
Używamy opcji -c (utwórz), aby utworzyć plik biblioteki, opcji -r (dodaj z zastąpieniem), aby dodać pliki do pliku biblioteki, oraz opcji -s (indeks), aby utworzyć indeks plików wewnątrz plik biblioteki.
Nazwiemy plik biblioteki libcipher.a. Nazwę tę podajemy w linii poleceń wraz z nazwami plików obiektowych, które zamierzamy dodać do biblioteki.
ar -crs libcipher.a cipher_encode.o cipher_decode.o
Jeśli wymienimy pliki w katalogu, zobaczymy, że mamy teraz plik libcipher.a.
ls -l
Jeśli użyjemy opcji -t (tabela) z ar, możemy zobaczyć moduły wewnątrz pliku biblioteki.
ar -t libcipher.a
Tworzenie pliku nagłówkowego libcipher.h
Plik libcipher.h zostanie dołączony do każdego programu korzystającego z biblioteki libcipher.a. Plik libcipher.h musi zawierać definicję funkcji znajdujących się w bibliotece.
Aby utworzyć plik nagłówkowy, musimy wpisać definicje funkcji do edytora tekstu, takiego jak gedit. Nazwij plik „libcipher.h” i zapisz go w tym samym katalogu, co plik libcipher.a.
void cipher_encode(char *text); void cipher_decode(char *text);
Korzystanie z biblioteki libcipher
Jedynym pewnym sposobem przetestowania naszej nowej biblioteki jest napisanie małego programu, który będzie z niej korzystać. Najpierw utworzymy katalog o nazwie test.
mkdir test
Skopiujemy bibliotekę i pliki nagłówkowe do nowego katalogu.
cp libcipher.* ./test
Przejdziemy do nowego katalogu.
cd test
Sprawdźmy, czy są tutaj nasze dwa pliki.
ls -l
Musimy stworzyć mały program, który będzie mógł korzystać z biblioteki i udowodnić, że działa zgodnie z oczekiwaniami. Wpisz następujące wiersze tekstu w edytorze. Zapisz zawartość edytora do pliku o nazwie „test.c” w katalogu test.
#include#include #include "libcipher.h" int main(int argc, char *argv[]) { char text[]="newsblog.pl loves Linux"; puts(text); cipher_encode(text); puts(text); cipher_decode(text); puts(text); exit (0); } // end of main
Przebieg programu jest bardzo prosty:
Zawiera plik libcipher.h, dzięki czemu można zobaczyć definicje funkcji biblioteki.
Tworzy ciąg o nazwie „tekst” i przechowuje w nim słowa „newsblog.pl loves Linux”.
Drukuje ten ciąg na ekranie.
wywołuje funkcję cipher_encode () w celu zakodowania łańcucha i wypisuje zakodowany łańcuch na ekranie.
Wywołuje cipher_decode () w celu zdekodowania ciągu i wypisuje zdekodowany ciąg na ekranie.
Aby wygenerować program testowy, musimy skompilować program test.c i dowiązać do biblioteki. Opcja -o (wyjście) mówi gcc, co ma wywołać program wykonywalny, który generuje.
gcc test.c libcipher.a -o test
Jeśli gcc po cichu powróci do wiersza poleceń, wszystko jest w porządku. Przetestujmy teraz nasz program. Moment prawdy:
./test
I widzimy oczekiwany wynik. Program testowy drukuje zwykły tekst, drukuje zaszyfrowany tekst, a następnie drukuje odszyfrowany tekst. Korzysta z funkcji w naszej nowej bibliotece. Nasza biblioteka działa.
Powodzenie. Ale po co na tym poprzestać?
Dodawanie kolejnego modułu do biblioteki
Dodajmy do biblioteki kolejną funkcję. Dodamy funkcję, której programista może użyć do wyświetlenia wersji biblioteki, której używa. Będziemy musieli stworzyć nową funkcję, skompilować ją i dodać nowy plik obiektu do istniejącego pliku biblioteki.
Wpisz następujące wiersze w edytorze. Zapisz zawartość edytora do pliku o nazwie cipher_version.c, w katalogu biblioteki.
#includevoid cipher_version(void) { puts("newsblog.pl :: VERY INSECURE Cipher Library"); puts("Version 0.0.1 Alphan"); } // end of cipher_version
Musimy dodać definicję nowej funkcji do pliku nagłówkowego libcipher.h. Dodaj nowy wiersz na dole tego pliku, tak aby wyglądał tak:
void cipher_encode(char *text); void cipher_decode(char *text); void cipher_version(void);
Zapisz zmodyfikowany plik libcipher.h.
Musimy skompilować plik cipher_version.c, aby uzyskać plik obiektowy cipher_version.o.
gcc -c cipher_version.c
Spowoduje to utworzenie pliku cipher_version.o. Możemy dodać nowy plik obiektowy do biblioteki libcipher.a za pomocą następującego polecenia. Opcja -v (gadatliwa) sprawia, że zwykle milczący ar mówi nam, co zrobił.
ar -rsv libcipher.a cipher_version.o
Nowy plik obiektu zostanie dodany do pliku biblioteki. ar drukuje potwierdzenie. „A” oznacza „dodane”.
Możemy użyć opcji -t (tabela), aby zobaczyć, jakie moduły znajdują się w pliku biblioteki.
ar -t libcipher.a
W naszym pliku biblioteki znajdują się teraz trzy moduły. Skorzystajmy z nowej funkcji.
Korzystanie z funkcji cipher_version ().
Usuńmy starą bibliotekę i plik nagłówkowy z katalogu testowego, skopiujmy nowe pliki, a następnie wróćmy do katalogu testowego.
Usuniemy stare wersje plików.
rm ./test/libcipher.*
Skopiujemy nowe wersje do katalogu testowego.
cp libcipher.* ./test
Przejdziemy do katalogu testowego.
cd test
Teraz możemy zmodyfikować program test.c, aby używał nowej funkcji biblioteki.
Musimy dodać nową linię do programu test.c, który wywoła funkcję cipher_version (). Umieścimy to przed pierwszym wstawieniem (tekst); linia.
#include#include #include "libcipher.h" int main(int argc, char *argv[]) { char text[]="newsblog.pl loves Linux"; // new line added here cipher_version(); puts(text); cipher_encode(text); puts(text); cipher_decode(text); puts(text); exit (0); } // end of main
Zapisz to jako test. C. Teraz możemy go skompilować i sprawdzić, czy nowa funkcja działa.
gcc test.c libcipher.a -o test
Uruchommy nową wersję testu:
Nowa funkcja działa. Wersję biblioteki możemy zobaczyć na początku wyjścia z testu.
Ale może być problem.
Zastępowanie modułu w bibliotece
To nie jest pierwsza wersja biblioteki; to jest druga. Nasz numer wersji jest nieprawidłowy. Pierwsza wersja nie zawierała funkcji cipher_version (). Ten ma. Więc to powinna być wersja „0.0.2”. Musimy zamienić funkcję cipher_version () w bibliotece na poprawioną.
Na szczęście ar sprawia, że jest to bardzo łatwe.
Najpierw edytujmy plik cipher_version.c w katalogu biblioteki. Zmień tekst „Wersja 0.0.1 Alfa” na „Wersja 0.0.2 Alfa”. To powinno wyglądać tak:
#includevoid cipher_version(void) { puts("newsblog.pl :: VERY INSECURE Cipher Library"); puts("Version 0.0.2 Alphan"); } // end of cipher_version
Zapisz ten plik. Musimy go ponownie skompilować, aby utworzyć nowy plik obiektowy cipher_version.o.
gcc -c cipher_version.c
Teraz zastąpimy istniejący obiekt cipher_version.o w bibliotece naszą nowo skompilowaną wersją.
Wcześniej używaliśmy opcji -r (dodaj z zamianą), aby dodać nowe moduły do biblioteki. Kiedy użyjemy go z modułem, który już istnieje w bibliotece, ar zastąpi starą wersję nową. Opcja -s (indeks) zaktualizuje indeks biblioteki, a opcja -v (szczegółowa) sprawi, że ar powie nam, co zrobił.
ar -rsv libcipher.a cipher_version.o
Tym razem ar donosi, że zastąpił on moduł cipher_version.o. Litera „r” oznacza zastąpienie.
Korzystanie z zaktualizowanej funkcji cipher_version ()
Powinniśmy skorzystać z naszej zmodyfikowanej biblioteki i sprawdzić, czy działa.
Skopiujemy pliki biblioteki do katalogu testowego.
cp libcipher.* ./test
Przejdziemy do katalogu testowego.
cd ./test
Musimy ponownie skompilować nasz program testowy z naszą nową biblioteką.
gcc test.c libcipher.a -o test
A teraz możemy przetestować nasz program.
./test
Wynik programu testowego jest taki, jakiego się spodziewaliśmy. W ciągu wersji jest wyświetlany poprawny numer wersji, a procedury szyfrowania i deszyfrowania działają.
Usuwanie modułów z biblioteki
Po tym wszystkim wydaje się szkoda, ale usuńmy plik cipher_version.o z pliku biblioteki.
Aby to zrobić, użyjemy opcji -d (usuń). Użyjemy również opcji -v (verbose), aby ar mówił nam, co zrobił. Dodamy również opcję -s (indeks), aby zaktualizować indeks w pliku biblioteki.
ar -dsv libcipher.a cipher_version.o
ar zgłasza, że usunął moduł. Litera „d” oznacza „usunięte”.
Jeśli poprosimy ar, aby wyświetlić listę modułów w pliku biblioteki, zobaczymy, że wróciliśmy do dwóch modułów.
ar -t libcipher.a
Jeśli zamierzasz usunąć moduły ze swojej biblioteki, pamiętaj o usunięciu ich definicji z pliku nagłówkowego biblioteki.
Udostępnij swój kod
Biblioteki umożliwiają udostępnianie kodu w praktyczny, ale prywatny sposób. Każdy, komu przekażesz plik biblioteki i plik nagłówkowy, może korzystać z Twojej biblioteki, ale rzeczywisty kod źródłowy pozostaje prywatny.
newsblog.pl
Maciej – redaktor, pasjonat technologii i samozwańczy pogromca błędów w systemie Windows. Zna Linuxa lepiej niż własną lodówkę, a kawa to jego główne źródło zasilania. Pisze, testuje, naprawia – i czasem nawet wyłącza i włącza ponownie. W wolnych chwilach udaje, że odpoczywa, ale i tak kończy z laptopem na kolanach.