ДИНАМИЧЕСКИЕ БИБЛИОТЕКИ!?

Сегодня мы здесь, чтобы поговорить о библиотеках. Кто они такие? Как мне их использовать? Как мне их сделать? Зачем мне их использовать?

Что такое библиотеки?

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

Эти файлы организованы в коллекцию. Статические библиотеки хранятся в файлах .a, а динамические — в файлах .so. Мы будем смотреть на файлы .so, которые являются расширением файла для динамической библиотеки C в Linux.

Существует два типа библиотек C: статические и динамические. В этой статье я расскажу, как создавать и внедрять динамические библиотеки, но краткое определение того, что они собой представляют, будет полезно.

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

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

Преимущество статики в том, что в конце находится только один файл, и вам не нужно отправлять дополнительные библиотеки вместе с вашим продуктом. Недостатком является то, что если вам нужно изменить эти функции или что-то еще в библиотеке, вам нужно перекомпилировать и распространять исполняемый файл. Кроме того, это делает файл намного большего размера, поскольку весь код должен быть записан для каждого вызова функции в исполняемый файл.

Где, как и в случае с динамической библиотекой, вы можете просто обновить библиотеку, чтобы изменить функции и обновить их. Поскольку программа ссылается на библиотеку для использования функции, она делает программу намного меньше, чем при использовании статических библиотек. Однако затем вам необходимо, чтобы библиотеки поставлялись с вашей программой.

Зачем мне их использовать?

Допустим, вы только что вернулись из ИКЕА, и у вас есть полная упаковка вашего нового письменного стола. Вы приносите его домой и собираете, затем подключаете к нему свой компьютер и играете в игру или пишете статью. Вы встаете и делаете что-то еще, а затем решаете, что вам нужно снова использовать свой компьютер, поэтому выбрасываете свой стол и строите новый.

Кажется безумным, верно? Хорошо, если мы тратим время на создание функций с нуля и учимся их использовать, зачем нам их выбрасывать и переписывать каждый раз, когда мы создаем новую программу?

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

Что ж, к счастью, функции можно записывать в файлы .c и просто ссылаться на них в заголовочном файле нашей основной программы. Отлично, все идет хорошо, и моя основная программа не такая уж и длинная и сложная, просто получил хороший заголовочный файл со всеми моими прототипами функций и моими файлами .c снаружи с моей функцией в нем.

Но подождите, теперь у меня есть 30 функций в моей программе и должно быть 30 соответствующих файлов функций вне моей основной программы, которые я должен скомпилировать с моим main.c?

Здесь на помощь приходят библиотеки. Мы можем объединить все 30 этих функций в один файл и просто ссылаться на библиотеку при компиляции, и все будет отлично и компактно.

Итак, как мне сделать библиотеку?

Опять же, в этой статье мы сосредоточимся только на создании статической библиотеки.

Итак, я упоминал ранее, что мы получаем все наши функции в одном месте, а затем компилируем их в файлы .o или объектные файлы. Используйте небольшой флаг в GCC, чтобы остановить процесс компиляции перед компоновкой. Немного похоже на это…

gcc -с *.с

Эта команда скомпилирует все файлы .c в текущем каталоге в файлы .o.

Для статических библиотек этого достаточно, так как приходится компилировать с дополнительными флагами, касающимися динамических библиотек. Мы включаем флаг -fPIC, чтобы сделать код независимым от позиции. Это означает, что мы даем коду относительный адрес вместо абсолютного адреса. Это помогает, если библиотека хочет быть загружена другими программами, и код пытается загрузить ее, скажем, по адресу 111 в одной виртуальной памяти, не имеет смысла загружать ее по адресу 111 в другой виртуальной памяти.

Мы также включаем флаг -Wall, чтобы показывать все предупреждающие сообщения, а не скрывать их. Это позволит нам отслеживать ошибки в нашем коде. Наша последняя команда gcc будет выглядеть так:

gcc -Стена -fPIC -c *.c

И наш каталог будет выглядеть так после компиляции.

Отлично, теперь у меня есть куча файлов .o, а также файлы .c? ФАЙЛОВ БОЛЬШЕ, ЧЕМ КОГДА-ЛИБО! Держись, держись. Теперь мы компилируем их в наш файл .so. Этот выглядит так…

gcc -shared -o libholberton.so *.o

Здесь мы фактически создаем нашу библиотеку. Команда -shared позволяет нам скомпилировать нашу библиотеку в общий объект, который мы можем скомпилировать с другими файлами для создания исполняемого файла. Команда -o позволяет нам переименовать наш выходной файл во что угодно. При именовании библиотек нам нужно использовать соглашение об именах lib(имя библиотеки).so. *.o означает, что мы хотим объединить все объектные файлы (.o) в нашу библиотеку.

Теперь у нас есть наша библиотека!

После того, как у нас есть наша библиотека, мы можем проверить ее содержимое с помощью следующей команды nm…

nm -D libholberton.so

Флаг -D используется для отображения динамических символов вместо обычных символов. Это вырезает часть ошибочных данных в списке символов.

Так как же нам использовать только что созданную библиотеку?

Теперь все, что осталось, это включить нашу библиотеку в нашу команду gcc, и мы можем покончить со всеми нашими надоедливыми функциональными файлами!!

Итак, до того, как мы должны были вызывать наши функции по отдельности в нашей команде компиляции с помощью gcc, мы могли просто вызвать библиотеку со всеми нашими функциями в ней и наш main.c…

Любая из вышеперечисленных работ. -Л. указывает искать в текущем каталоге (.), а -lholberton просто избавляется от lib и .so в имени нашего файла.

Есть еще один шаг к использованию наших динамических библиотек, и это позволяет нашей программе найти нашу библиотеку. Для этого мы используем переменную среды LD_LIBRARY_PATH, чтобы сообщить системе, где она находится.

Мы можем проверить, все ли наши библиотеки найдены с помощью команды ldd. Он печатает все общие библиотеки, необходимые вашей программе, и может ли он найти библиотеку или нет.

Теперь, пока ваши прототипы объявлены в вашем основном файле или в заголовке, который связан с вашим основным файлом, все должно компилироваться просто отлично!