Здравствуйте, уважаемые подписчики. У меня опять есть для вас несколько важных новостей.
1) Сайт в очередной раз переехал. Я сменил хостинг с by.ru на amillo.net. By.ru - это хороший хостинг (среди бесплатных), однако на нем возникают проблемы скачивания больших архивов. В связи с этим приношу свои извинения за причененные неудобства, но это нужно было сделать. Надеюсь, что этот переезд будет последним до переезда на платный хостинг, который я планирую произвести через 8-9 месяцев. Теперь адрес сайта http://linux.amillo.net
2) Сайт пополнился новыми электронными книгами. Подобные пополнения будут происходить еженедельно.
3) Раздел "Вопросы и ответы" больше не будет выходить в рассылке и скоро появится на сайте.
В настоящем выпуске будет рассмотрена концепция создания динамических библиотек. Этот раздел прост для понимания, но при выполнении примеров требуется внимательность и аккуратность.
2. Программирование в Linux
2.1. Разбор домашнего задания
Реализуйте на языке C++ функцию с именем xabs, возвращающую абсолютное значение числа. Перегрузите функцию для целого аргумента и для аргумента с плавающей десятичной точкой. Для реализации используйте abs() и fabs().
Домашнее задание 5.1
Разбор домашнего задания
Итак, реализация данной перегрузки будет осуществляться следующим образом:
Теперь если функция вызывается с целым аргументом, выполняется первый вариант xabs. Если же функция вызывается с вещественным аргументом (имеется в виду компьютерная абстракция вещественных чисел - числа с плавающей точкой), то вызывается второй вариант xabs.
2.2. Создание динамических библиотек
Перед чтением данного материала следует вспомнить обсуждавшиеся ранее особенности статических и динамических библиотек. Чтобы не изобретать велосипеды, для изучения данного материала воспользуемся старым примером программы нахождения среднего арифметического квадратов двух чисел.
Сделаем так, чтобы в качестве сервера были не объектные файлы, а динамическая библиотека. Итак, библиотека - это просто несколько скомпонованных особым образом объектных файлов. Идеальным вариантом в данном случае будет компоновка файлов mid.o и sqr.o в библиотеку, например, libmidsqr.so. В Linux имена динамических библиотек как правило начинаются с префикса lib и имеют расширение .so, однако часто после .so через точку указывается версия библиотеки, а чтобы версия не мешала, используют систему символических ссылок. Статические библиотеки имеют расширение .a.
Чтобы заставить компилятор создавать не исполняемый файл, а совместно используемую (динамическую) библиотеку, используется опция -shared. Чтобы подключить библиотеку к исполняемому файлу, используют опцию -l с аргументом, которым является имя библиотеки без lib вначале и без .so в конце. Здесь, как и в большинстве случаев, касающихся GCC-компиляторов, аргумент не принято отделять пробелом от опции. То есть, наша библиотека будет подключаться к файлу main при помощи опции -lmidsqr.
Если препроцессор ищет хэдэры (заголовочные файлы) в текущем каталоге и в предопределенных каталогах (таких как /usr/include), то линковщик (сборщик) при подключении библиотеки ищет эту библиотеку только в предопределенных каталогах (таких как /usr/lib). Таким образом, чтобы подключить нашу библиотеку к исполняемому файлу main, следует указать линковщику текущий каталог. Насколько нам известно, текущий каталог обозначается символом . (точка). Чтобы заставить линковщих искать библиотеки в указанном каталоге используется опция -L, аргументом которой является каталог (или каталоги). Таким образом, мы должны будем указать опцию L.(L и точка)
При подключении библиотеки к исполняемому файлу, в этот исполняемый файл добавляется информация о том, в каком каталоге искать библиотеку при выполнении (помните, код из динамических библиотек не помещается в исполняемый файл, а помещаются лишь ссылки). Чтобы указать этот каталог, используется сложная опция -Wl,-rpath,КАТАЛОГ. В данном случае мы укажем -Wl,-rpath,.(точка - текущий каталог). Есть и другой способ указать местоположение библиотеки, но о нем мы поговорим в последующих выпусках рассылки.
Для того, чтобы сформировать библиотеку из объектных файлов, эти объектные файлы нужно компилировать особым образом. Компилятор должен сформировать так называемый PIC-код (Position Independent Code - позиционно независимый код). Что он означает, мы рассмотрим тогда, когда будем изучать ассемблер в Linux. А сейчас запомним, что опция -fPIC позволяет генерировать позиционно-независимый код.
Теперь, когда все разобрано по полочкам, можно легко разобраться в следующем Makefile'е:
# Makefile for MidSqr-project
main: main.o libmidsqr.so
g++ -o main main.o -lmidsqr -L. -Wl,-rpath,.
Однако вопрос вызывает целевой модуль clean, у которой нет зависимостей. В нем нет ничего особенного. Утилита make может выполнять любые команды интерпретатора. Почему бы не создать целевой модуль очистки, который удаляет все, что создано ранее (кроме исходных файлов). Команда
|$ make clean
удаляет все динамические библиотеки, все объектные файлы и исполняемый файл main в текущем каталоге. Цель clean не имеет зависимостей, поэтому данный вызов не приведет к выполнению команд других целевых модулей. Кроме того, ни один целевой модуль данного Makefile'а не зависит от модуля clean, поэтому вызов make без аргументов не приведет к удалению файлов. Не забывайте перед командами в Makefile ставить табуляции.
Домашнее задание будет следующее:
Узнайте (а если знаете, то повторите), что такое ссылка в файловой системе. Узнайте также, чем символическая ссылка отличается от жесткой. Домашнее задание 6.1