Создание собственной разделяемой библиотеки в С

Разделяемые библиотеки — это такие библиотеки, которые загружаются приложением во время его загрузки. Их могут использовать все приложения системы.
Разделяемые библиотеки имеют несколько имён.
soname — состоит из префикса «lib», имени библиотеки, расширения «.so» после которого следует версия библиотеки.
real name — имя файла, который содержит реализацию библиотеки
linker name — тоже что и soname но без указания версии.

После маленького вступления приступим к созданию нашей библиотеки.
Создадим её реализацию — libhello.c:

#include <stdio.h>

void say_hello() {
    printf("Привет мир!\n");
}

Определим прототип функции в заголовочном файле — libhello.h:

void say_hello();

После этого можно приступать к компилированию библиотеки.
Генерируем объектный файл библиотеки (учтите что он должен быть позиционно независимым, необходимо указывать флаг -fPIC)

gcc -fPIC -Wall -g -c libhello.c

Теперь создадим библиотеку указав её soname, версию и объектный файл с реализацией:

gcc -g -shared -Wl,-soname,libhello.so.0 -o libhello.so.0.0 libhello.o -lc

В результате будет создан файл libhello.so.0.0.
Добавим библиотеку в список:

/sbin/ldconfig -v -n .

Создаём символьную ссылку на файл (для linker name):

ln -sf libhello.so.0 libhello.so

Библиотека готова к использованию. Учтите, что мы не перемещали её в стандартные каталоги библиотек. Так что необходимо будет указывать компилятору где она находится.

Приведём пример использования.
Создайте файл demo.c:

#include "libhello.h"

int main(){
  say_hello();
  return 0;
}

Компилировать его необходимо такой командой:

gcc demo.c -o demo -lhello -L.

Можете попробовать выполнить полученный файл demo:

$ ./demo
Привет мир!

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

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.

Получилось? Отлично…
Теперь удалите файлы библиотеки и запустите программу:

$ ./demo
./demo: error while loading shared libraries: libhello.so.0: cannot open shared object file: No such file or directory

Это доказывает, что мы всё сделали правильно! Приложение не нашло библиотеку и отказалось запускаться.

Проверить какие библиотеки необходимы для запуска приложения можно при помощи утилиты ldd. Верните на место библиотеку чтобы получилось как у меня.

$ ldd demo
    linux-vdso.so.1 =>  (0x00007fffa4dff000)
    libhello.so.0 (0x00007f8324745000)
    libc.so.6 => /lib/libc.so.6 (0x00007f83243a2000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f8324949000)

Как видите в списке есть наша библиотека.
Ну а если её нет в каталоге вывод таков:

$ ldd demo
    linux-vdso.so.1 =>  (0x00007fff80557000)
    libhello.so.0 => not found
    libc.so.6 => /lib/libc.so.6 (0x00007f37a1a92000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f37a1e37000)

Библиотека не найдена. С чувством выполненного долга можно пойти попить чайку…

 

Похожий код:

Фото аватара
Алексей Петров

Программист, разработчик с 5 летним опытом работы. Учусь на разработчика игр на Unity и разработчика VR&AR реальности (виртуальной реальности). Основные языки программирования: C#, C++.

Оцените автора
Бла, бла код
Добавить комментарий