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

Огромные преимущества этого:

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

Чтобы это стало возможным, мы должны реорганизовать наш код и поместить его в библиотеку следующим образом:

  • один или несколько исходных файлов .c с кодом наших функций
  • один или несколько заголовочных файлов .h с типами (typedefs, structs и enums) и прототипами функций, которые мы хотим использовать.

Пример.

Это файл с парой простых функций сложения () и вычитания ().

В Linux мы можем создавать два типа библиотек: статические и динамические.

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

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

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

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

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

Создание статической библиотеки

Создадим статическую библиотеку, используя все файлы *.c в нашем текущем каталоге. Во-первых, нам нужно скомпилировать наши файлы C в объектный код. Мы можем сделать это, используя:

Далее нам нужно создать нашу статическую библиотеку и добавить в нее файлы. Мы можем сделать это с помощью команды:

После того, как мы добавили все в нашу стандартную библиотеку, библиотеку необходимо проиндексировать. Библиотеку можно проиндексировать, выполнив команду ranlib libexample.a. Индексация библиотеки важна, поскольку она ускоряет процесс компоновки при вызове библиотеки.

Мы можем увидеть наш недавно сгенерированный индекс, запустив команду nm libstatic.a. Команда Nm предоставляет дополнительную информацию о символах в нашей статической библиотеке. В частности, по умолчанию команда nm покажет нам виртуальный адрес символа, имя символа и информацию о типе символа. Если символ в нижнем регистре, то он локальный, если в верхнем регистре, то внешний.

Чтобы использовать эту статическую библиотеку, мы должны создать программу; Назовем его my_program.c, который использует функции из только что созданной библиотеки. Чтобы использовать библиотечные функции, нам нужно указать компилятору, где искать. Мы могли бы запустить команду:

Теперь давайте взглянем на динамические библиотеки. Давайте представим знакомый сценарий: у нас есть файл исходного кода, который вызывает библиотечную функцию mylib.so (обратите внимание на разницу в расширении файла. В Linux статические библиотеки должны заканчиваться на .a, а динамические — на .). Вместо компиляции реализации функции в объектный код и включения в исполняемый файл, в динамической библиотеке компоновщик будет просто включать адрес начала функции, которую мы пытаемся использовать в исполняемом файле. Это устраняет проблему размера, вызванную статическими библиотеками, поскольку окончательный исполняемый файл будет включать только адреса, а не полные реализации функций.

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

Создание динамической библиотеки

Давайте создадим динамическую библиотеку, используя все файлы *.c в нашем текущем каталоге. Сначала нам нужно скомпилировать наши файлы C в объектный код и сделать их независимыми от их положения. Мы можем сделать это, используя:

Далее нам нужно создать нашу динамическую библиотеку и добавить в нее файлы. Мы можем сделать это с помощью команды:

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

Программа должна знать, где искать файлы библиотеки. Поэтому нам нужно добавить расположение динамической библиотеки в среду LD_LIBRARY_PATH. Мы могли бы сделать это с помощью следующей команды:

Чтобы использовать эту динамическую библиотеку (liball.so), мы должны создать программу, назовем ее my_program.c. Допустим, эта программа использует функции из нашей динамической библиотеки. Далее нам нужно скомпилировать программу так же, как мы это делали со статической библиотекой:

После того, как мы создали эту новую общую библиотеку, мы можем использовать команду ldconfig для создания необходимых привязок и кэша (для использования компоновщиком runtime, ld.so) в /etc/ld.so. каталог конф.

Entonces, cuando decida си usar уна biblioteca estática о dinámica пункт су próximo proyecto, recuerde лас compensaciones. Si necesita ahorrar espacio, probablemente debería usar una biblioteca dinámica, si necesita Que las cosas se ejecuten más rápido, probablemente debería usar una biblioteca estática.