Определение
Библиотека — это коллекция реализаций поведения, написанная на определенном языке и обладающая продуманным интерфейсом, с помощью которого это поведение активируется. К примеру, разработчики, желающие написать высокоуровневую программу, могут вместо повторяющейся реализации системных вызовов использовать для их создания библиотеку. Кроме того, это поведение предоставляется для повторного использования многими независимыми программами (Wikipedia).
Зачем
В мире открытого программного обеспечения Linux является, пожалуй, лидирующей системой. Согласно английской Wikipedia, примерно на 80% серверов интернета установлена та или иная форма Linux/Unix. Сегодня поддержка этой ОС закладывается в основу большого числа проектов. Участие в создании или расширение имеющихся опенсорсных продуктов является наиболее эффективным способом быстрой разработки программ.
В этой статье мы рассмотрим основы разработки библиотеки Linux на С++, подготовив вас к переходу в мир открытого ПО.
Как
Для начала потребуется выбрать дистрибутив и либо установить его непосредственно на ПК, либо использовать через виртуальную машину. В этом руководстве я буду использовать Ubuntu Linux 22.04. В качестве редактора кода я выбрал VS Code, который можно найти в приложении Snap Store, предлагающем удобный способ скачивания и установки наиболее популярного ПО. А ведь еще недавно единственным способом установки программ в Ubuntu был ввод команд из терминала.
И хотя установка ПО через терминал несколько медлительна, сам по себе этот инструмент является незаменимым помощником для разработчиков. Использование терминала в сочетании с горячими клавишами позволяет делать все быстрее, не отводя рук от клавиатуры.
Создание проекта в VS Code
Для быстрого запуска терминала нажмите ⊞ Win
или ⌘ Cmd
на клавиатуре Mac и введите terminal
, нажмите Enter. После открытия терминала нужно создать каталог для проекта по следующему пути:
mkdir ~/Desktop/linux-shared-library
Теперь используем терминал для открытия созданного проекта в VS Code. Здесь можно задействовать сокращенную команду !$
, чтобы автоматически подставить часть ~/Desktop/linux-shared-library
из команды выше и передать ее в редактор кода. Вот как это делается:
code !$
Теперь у вас должно открыться окно VS Code, и можно приступать.
В VS Code имеется встроенный терминал для упрощения доступа. Этот терминал можно автоматически активировать нажатием Ctrl + ~
.
Пишем main
Откройте терминал VS Code и создайте файл:
code main.cpp
Запишите в него следующий код:
// Позволяет ссылаться на встроенные функции ввода/вывода // стандартной библиотеки.
#include <stdio.h>
// Реализация функции: int (возвращаемый тип), main (имя // функции), void (тип параметра)
int main(void)
{
// Используем стандартную библиотеку для вывода в окно терминала.
puts("Hello Earth!");
// Выходим с кодом возврата 0, обозначающим успех.
return 0;
}
Это программа, которая будет потреблять библиотеку.
Далее мы скомпилируем и выполним только что написанный код с помощью компилятора gcc, поставляемого вместе с дистрибутивом Ubuntu. Устанавливается он так:
gcc main.cpp
Вышеприведенная команда сгенерирует файл a.out
, который при выполнении командой ./a.out
в терминале VS Code будет выводить “Hello Earth!”:
Вы только что скомпилировали и выполнили программу С++! Далее мы разберем, как писать код, которым можно будет делиться с миром.
Написание общей библиотеки
Создайте через терминал VS Code новый файл:
code mars.cpp
В этот файл внесите следующий код:
// Позволяет ссылаться на встроенные функции ввода/вывода // стандартной библиотеки.
#include <stdio.h>
// Определение функции: void (возвращаемый тип), foo (имя функции), // void (тип параметра).
void mars(void)
{
// Используем стандартную библиотеку для вывода в окно терминала
puts("Hello Mars!");
}
Это уже код нашей библиотеки.
Дальше нужно создать заголовочный файл. В заголовочных файлах мы определяем, какие функции библиотека будет раскрывать ее потребителям:
code mars.h
Добавьте в него следующий код:
// Определяем макрос препроцессора, чтобы mars.h включался только // раз.
#ifndef mars_h__
#define mars_h__
// Экспортируем функцию mars в библиотеку, делая доступной для // других проектов.
extern void mars(void);
#endif // mars_h__
Далее нужно скомпилировать код библиотеки, чтобы ее могла использовать программа main.cpp
. Это делается в два шага: сначала компилируем код в mars.cpp
в виде позиционно-независимого кода, чтобы его можно было добавить в общую библиотеку:
gcc -c -fpic -o mars.o mars.cpp
В результате будет создан объектный файл mars.o
. Этот файл мы используем для создания библиотеки:
gcc -shared -o libmars.so mars.o
Теперь можно использовать его в программе main. cpp
.
Интегрирование библиотеки
Добавим в main.cpp
следующее:
// Позволяет ссылаться на встроенные функции ввода/вывода // стандартной библиотеки.
#include <stdio.h>
+#include "mars.h"
// Реализация функции: int (возвращаемый тип), main (имя функции), // void (тип параметра).
int main(void)
{
// Используем стандартную библиотеку для вывода в терминал.
puts("Hello Earth!");
+ // Вызываем функцию в общей библиотеке.
+ mars();
// Выходим с кодом возврата 0, означающим успех.
return 0;
}
Здесь мы описали процесс использования функции mars
из общей библиотеки.
Теперь скомпилируем программу main
и свяжем ее с библиотекой mars
. Компилятор gcc предполагает, что имена файлов общих библиотек должны начинаться с lib
, поэтому нужно указать, что мы хотим провести линковку с libmars.so
. Делается это так:
gcc main.cpp -lmars
Еще нужно сказать gcc, где искать libmars.so
. Попробуем снова, но уже с аргументом -L
, указывающим расположение библиотеки. О том, что файл доступен в данном каталоге, можно сообщить gcc так:
gcc -L./ main.cpp -lmars
Запускаем скомпилированную программу:
./a.out
Она не может загрузить созданную нами библиотеку. Просто мы не указали, откуда общие библиотеки нужно загружать. Делается это с помощью -Wl,-rpath
:
gcc -L./ -Wl,-rpath=./ main.cpp -lmars
Вот и все! Запускайте скомпилированную программу и убедитесь, чтобы вывод совпал со следующим:
Если вы вдруг захотите перейти на следующий уровень создания общих библиотек, то подумайте о написании такой для Unreal Engine.
Читайте также:
- Язык C: введение и настройка среды
- Как компилировать ZXing C++ в Wasm, используя WASI SDK в Linux
- Чем отличается C++ от C#?
Читайте нас в Telegram, VK и Дзен
Перевод статьи Bobby Galli: How to Build a Linux Shared Library