Использование библиотек

Библиотеки нужны для того, что бы не нужно было по нескольку раз писать некоторый код. Этот код(к примеру некоторая функция) помещается в библиотеку, представляющую сабой коллекцию обычных объектных файлов.

Библиотеки бывают статические и динамические. Если мы используем статическую библиотеку, то эта библиотека, а точнее один из объектных файлов этой библиотеки, будет полностью подключаться к нашей программе. То есть если у нас есть 10 программ, использующих нашу библиотеку, то код всего объектного файла с нашей функцией будет присутствовать в памяти 10 раз.

Динамическая библиотека в отличие от статической присутствует в памяти в одном экземпляре, а в программе присутствует только ссылка на необходимую нам функцию. То есть загрузка библиотеки в память происходит только при первом вызове функции, в остальных же случаях просто увеличивается счётчик использующих библиотеку программ. При выгрузке аналогично. То есть библиотека предстает перед нами как обычный разделяемый ресурс.
Разберем создание статических библиотек

Имя библиотеки принято начинать с lib. Разрешение должно быть .a Допустим у нас есть объектный файл test.o Для создания статической библиотеки служит команда
ar cr libtest.a test.o

где libtest.a--имя библиотеки, флаг cr указывает на необходимость создания библиотеки. Можно указывать несколько объектных файлов.

Далее при компиляции программы библиотека указывается следующим образом
g++ -o run main.o -L. -ltest

Подключаемую библиотеку необходимо указывать в конце командной строки(вернее после того, как было указано имя программы, использующей библиотеку). Просто линкер ищет неизвестные определения в библиотеках, следующих за определением самой программы.
Динамические библиотеки(shared librarys)

Объектный файл, который будет включен в динамическую библиотеку, должен быть скомпилирован с определенными опциями. Эта опция -fPIC. PIC - это position-independent code (позиционно-независимый код). Функция из динамической библиотеки может быть загружена по различным адресам в различных программах. Но код в объектном файле не должен быть зависимым от адреса по которому он будет загружен.
g++ -c -fPIC test.cpp

Динамическая библиотека создается следующей командой
g++ -shared -fPIC -o libtest.so test.o

Имя динамической библиотеки должно быть вида libXXX.so Можно также указать несколько объектных файлов. Линкуется динамическая библиотека также как и статическая.
g++ -o run main.o -L. -ltest

Если статическая и динамическая библиотека находятся вместе, то предпочтение отдается динамической библиотеки. Для указания того, что нам необходима статическая библиотека, необходимо указать опцию линкера -static
g++ -static -o run main.o -L. -ltest

Для просмотра динамических библиотек, необходимых программе, используется команда
ldd run

где run--имя исполняемого файла.

Следует заметить, что если мы подключаем динамическую библиотеку, которая ссылается на другие библиотеки, то эти библиотеки будут тоже подгружены. Если подключается статическая библиотека, то такого не будет. Все придется подключать вручную.
Загрузка библиотеки в коде программы
void* handle=dlopen("libtest.so",RTLD_LAZY);//возвращает дескриптор динамической библиотеки. Если неуспешно то NULL
assert(handle);
void* adress=dlsym(handle,"func");//получаем адрес нужной нам функции. Если неуспешно, то NULL
assert(adress);
void (*test)();
test=(void (*)())adress;
(*test)();
dlclose(handle);//закрытие библиотеки

второй параметр в функции dlopen показывает формат символических имен в динамической библиотеки. В программе должна быть подключена библиотека dlfcn.h Программа должна компилироваться с подключением библиотеки dl
-ldl

В библиотеке функция должна быть определена следующим образом
extern "C" void func()

Это необходимо для того, что бы при компиляции компилятор не изменял имя функции, что он обычно делает для обеспечения прегрузки операторов.

RSS-материал