Cвоя библиотека my_library.a в языке Си для начинающих
Всем привет! Я Стас harrioho, учащийся Ярославского кампуса School 21. В нашем сообществе нет преподавателей, мы учимся сами и учим друг друга. В этой статье рассказываю, как при разработке на языке Си избежать дублирования кода, и вынести его в собственную библиотеку.
Заголовочный файл VS библиотека
Самым первым и самым очевидным способом избежать дублирования кода является применение собственного заголовочного файла: например my_library.h, и подключение его в свои проекты с помощью директивы #include. Но есть нюанс.
Заголовочный файл содержит подключения других заголовочных файлов, директивы препроцессора, определения функций, структур, но не содержит реализации. Получается, к каждому собственному заголовочному файлу my_library.h, нужно написать как минимум один файл реализации my_library.с, и включать в проект их оба. А что если для каждой функции из заголовочного файла написан отдельный файл реализации? Проект обрастает модулями, как корабль ракушками, потеряться в которых становится проще простого.
Библиотека же представляет из себя единый предварительно скомпилированный файл. Подключив его в свою программу, программист сокращает количество кода и модулей в своём проекте, экономит время и ресурсы.
Статические и динамические библиотеки
К программе на Си можно подключать статические(my_library.a, my_library.lib) и динамические(my_library.so, my_libraby.dll) библиотеки. Они обе предварительно скомпилированы, содержат в себе реализации функций.
Код динамической библиотеки загружается в оперативную память при выполнении программы, а исполняемый файл содержит ссылки на функции в динамической библиотеке, а не сам код. Как правило, программа поставляется без динамической библиотеки, и становится зависимой от того, есть ли требуемые .dll на целевой машине.
Код статической библиотеки включается в исполняемый файл на этапе компиляции. Это означает, что все необходимые функции из библиотеки копируются в конечный исполняемый файл. Из-за этого он может быть значительно больше, зато обеспечивают более высокую производительность, так как все функции уже находятся в исполняемом файле и не требуют дополнительных затрат на загрузку.
Практика
Напишем с применением статической библиотеки простую программу, которая будет выводить в консоль “Hello world!”. Для этого декомпозируем программу на модули, и напишем их код:
my_library.h
main.c
my_hello.c
my_world.c
Теперь соберём реализацию функций my_hello и my_world в статическую библиотеку. Перед этим файлы Си нужно преобразовать в объектные файлы передав компилятору флаг -с:
Получаем два новых файла my_hello.o и my_world.o, из которых и будет состоять библиотека. Сборку произведём специальной утилитой ar (сокр. archiver):
Здесь:
ar – вызываемая утилита
crs – три отдельных флага утилиты, написанных слитно. Значения флагов можно почитать в консоли man ar.
После того, как мы получили предварительно скомпилированную библиотеку, для чистоты эксперимента мы удалим исходные и объектные файлы my_hello и my_world, так что в нашем проекте останутся только my_library.h, my_library.a и main.c
Скомпилируем исполняемую программу:
Здесь:
-o hello сообщает компилятору имя создаваемой программы
-L. в gcc флаг указывает путь до присоединяемой библиотеки или заголовочного файла. У нас файл лежит в одной директории с main, поэтому путь - точка
-Wall -Werror –Wextra используются для управления предупреждениями, которые компилятор выдает во время компиляции кода.
Итак, в директории с нашей программой появился новый исполняемый файл hello. Запустим его командой:
И увидим в консоли ожидаемое «Hello world!». Наша программа собрана и работает успешно.
Понравилась статья? Перешли её соседу слева и соседу справа. Всем лёгкого кода и peer-to-peer!