Скажімо, у вас є клас, Unuseful
визначений таким чином:
Файл Unuseful.h
:
class Unuseful {
public:
void printUnusefulStatement();
};
Файл Unuseful.cpp
:
#include "unuseful.h"
#include <iostream>
void Unuseful::printUnusefulStatement()
{
std::cout << "Hello world!" << std::endl;
}
Тепер у вас є інший клас, який потребує друку некорисних виписок:
Unuseful u;
u.printUnusefulStatement();
Це означає, що ви хочете використовувати зовнішню бібліотеку, що містить конкретну реалізацію ( printUnusefulStatement
), яку ви хочете включити у свій код.
Ви можете використовувати цю бібліотеку двома способами:
- Надаючи компілятору вихідний код
- Надавши двійковий файл (який раніше був скомпільований для вашої архітектури), компонувальнику
Випадок 1: використання бібліотеки під час компіляції
Це найпростіший випадок. У вас є вихідний код бібліотеки, яким ви повинні скористатися, і вам просто потрібно скомпілювати його разом із наявним кодом (скажімо, main.cpp
файлом). Зазвичай ви є автором і користувачем бібліотеки (класу, який виконує потрібне вам завдання).
Компіляція за допомогою цієї команди:
g++ main.cpp unuseful.cpp
дозволяє використовувати необхідну реалізацію у вашому main.cpp
файлі.
Випадок 2: зв’язок бібліотеки
Частіше, ніж у випадку 1 , у вас немає вихідного коду бібліотеки, яку ви хочете використовувати. У вас є лише файл заголовка ( Unuseful.h
, щоб продовжити приклад) і статична або спільна бібліотека (можливо, [*] libunuseful.a
та libunuseful.so
файли відповідно).
Статична бібліотека - це архів об’єктних файлів ( *.o
), які зв’язані всередині кінцевих виконуваних файлів, а спільні бібліотеки натомість завантажуються динамічно - під час виконання (дивіться на цій сторінці для кращого розуміння різниці ).
Статичні бібліотеки створюються простим архівуванням *.o
файлів за допомогою ar
програми:
# Create the object files (only one here)
g++ -c unuseful.cpp
# Create the archive (insert the lib prefix)
ar rcs libunuseful.a unuseful.o
Спільні бібліотеки створюються з g++
-shared
опцією:
# Create the object file with Position Independent Code[**]
g++ -fPIC -c unuseful.cpp
# Crate the shared library (insert the lib prefix)
g++ -shared -o libunuseful.so unuseful.o
Припустимо, тепер у вас є Unuseful.h
файл і спільна бібліотека ( libunuseful.so
файл), і у вас є main.cpp
файл, який створює екземпляр Unuseful
об’єкта і викликає printUnusefulStatement
метод.
Якщо ви спробуєте скомпілювати цей файл ( g++ main.cpp
), компонувальник скаржиться, оскільки не може знайти printUnusefulStatement
символ.
Пора користуватися бібліотекою:
g++ main.cpp -L. -lunuseful
-L
Опція повідомляє компоновщик , де шукати бібліотеки файлів і -l
прапор вказує компоновщик ім'я бібліотеки , які будуть використовуватися (безlib
префікса).
Тепер виконуваний файл ( a.out
тому що я не вказав інше ім'я) створений, і ви використали бібліотеку для реалізації потрібної вам функціональності ( printUnusefulStatement
).
Оскільки спільна бібліотека завантажується під час виконання, виконання a.out
виконуваного файлу може бути невдалим, оскільки система не може знайти бібліотеку. Зазвичай це може бути вирішено шляхом відповідного встановлення змінної середовища, що вказує, які шляхи використовувати для пошуку динамічних бібліотек:
# Set the LD_LIBRARY_PATH [*]
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
Готово, тепер ваш виконуваний файл скомпільовано, і він зможе запустити та завантажити потрібну йому бібліотеку.
Висновок
Це швидкий огляд бібліотек, який, я сподіваюся, може допомогти вам зрозуміти, як вони використовуються та надаються іншим.
Є багато багатьох аспектів, які слід дослідити більш докладно, якщо вас це цікавить: g++
параметри під час створення спільних бібліотек, ar
параметри, змінні середовища, формат спільних бібліотек тощо.
[*]: У середовищі Unix
" Цей параметр має значення для m68k, PowerPC та SPARC. Незалежний від позиції код вимагає спеціальної підтримки, тому працює лише на певних машинах. [Зі сторінки довідки g ++]
std::cout << "Hello World";
ви користуєтесь бібліотекою. Чи можете ви бути більш конкретними?