В Linux, как правило, файл-статическая_библиотека имеет расширение ".a"
2) Статические библиотеки на языке C.
Исходный код библиотеки:
######################
#include
extern int hello()
{
printf("Hello world! I'm static library\n");
return 0;
};
######################
Сохраните его в файле static.c
Ключевое слово extern необходимо для того, чтобы функция была видна в программе.
Теперь скомпилируем (! без линковки) библиотеку:
gcc -c static.c -o static.o
(на выходе имеем файл static.o, содержащий объектный код нашей библиотеки)
ar rc libMY_STATIC.a static.o
ar упаковывает несколько (! Это важно. Дело не ограничивается только одним объектным файлом) объектных файлов в одну статическую библиотеку. Статическая библиотека имеет расширение ".a", при этом ее название должно начинаться с "lib" (дань традиции).
Параметры ar:
r - предписывает заменять старые версии объектных файлов новыми - необходим для переупаковки библиотеки;
c - создать статическую библиотеку, если та еще не существует.
Проиндексируем функции внутри библиотеки для более быстрой линковки:
ranlib libMY_STATIC.a
Итак, мы получили статическую библиотеку libMY_STATIC.a.
Теперь попытаемся использовать библиотеку в нашей программе:
Исходный текст программы (C):
######################
#include
int main()
{
int x = hello();
printf("Return code: %d\n",x);
return 0;
}
######################
Сохраните его в файле program1.c
Способы связывания библиотеки и программы:
- Скомпилируем и слинкуем (в том числе с нашей библиотекой) нашу программу:
gcc program1.c libMY_STATIC.a
(предполагается, что в качестве аргумента gcc будут переданы полные пути (!) к вашим библиотекам)
И запустим:
./a.out
На выходе получим:
Hello world! I'm static library
Return code: 0
Отлично!
- Скомпилируйте с помощью команды:
gcc program1.c -L. -lMY_STATIC -o a1.out
Смысл аргументов:
-L - путь к каталогу, содержащему наши библиотек (используйте "-L -L - название нашей библиотеки (это важно - название (!), а не имя файла - собственно, если библиотека имеет своим именем "libBLABLABLA.a", то ее названием будет "BLABLABLA" - т.е. имя без приставки "lib" и расширения ".a") (для нескольких библиотек используйте "-l -l ...")
Запустите файл a1.out на выполнение и удостовертесь, что результаты те же, что и в предыдущем пункте.
- Видоизменим предыдущий способ - уберем аргументы "-L":
В начале проверим значение переменной LD_LIBRARY_PATH и содержимое файла /etc/ld.so.conf:
echo $LD_LIBRARY_PATH ; cat /etc/ld.so.conf
На экране появился некоторый список каталогов - это те каталоги, в которых система ищет библиотеки при их линковке с программой (еще к таким каталогам относятся:
/lib
/usr/lib
. Поместите libMY_STATIC.a в один из этих каталогов:
(Я, к примеру, засуну нашу библиотеку в каталог /usr/lib):
su -c 'cp libMY_STATIC.a /usr/lib'
(в Ubuntu - sudo cp libMY_STATIC.a /usr/lib)
ldconfig
(ldconfig обновляет кеш данных о библиотеках линковщика)
Теперь скомпилируем и запустим нашу программу:
gcc program1.c -lMY_STATIC -o a2.out
./a2.out
Результат:
Hello world! I'm static library
Return code: 0
Бинго! Кстати, таким вот способом вы можете подключать к своей программе любые статические библиотеки из приведенных выше каталогов.
* Бывает полезно определить все прототипы функций библиотеки в некотором заголовочном файле, который будет потом включаться в вашу программу. Это не обязательно, но удобно.
3) Статические библиотеки на языке Assembler.
Представьте, что вам необходимо оптимизировать выполнение некоторых действий в вашей программе. Разумеется, вы может применить ключевое слово asm (если пишите программу на C/C++), но лучшим решением будет создание оптимизированной вами библиотеки на языке Assembler и подключение ее к вашей программе. Давайте попробуем:
*Кстати, углубляться в процесс компиляции библиотеки и ее линковки с вашей программой я не буду (!). Этот процесс идентичен полностью (!) тому же процессу для библиотек, написанных на языке C.
Итак, имеем вот такую программу:
######################
#include
int main()
{
printf("Hello world!\n");
return 0;
};
######################
Сохраните ее в файле program2.c
Скомпилируйте ее и запустите:
gcc program2.c
./a.out
Я получил:
Hello world!
Отлично.
Я привел этот пример, чтобы показать действительно возможность оптимизации программы с помощью библиотеки на Assembler'е. Вы можете заметить, что вызов printf в main() не оптимален, т.к. printf, по крайней мере, один раз использует цикл while для поиска вхождений конструкций "%..." в строку. Это не оптимально, т.к. очевидно, что таковых символов у нас нет. Оптимизируем нашу программу с помощью библиотеки на Assebmler'е:
######################
.text
.globl my_printf
my_printf:
movl $4,%eax
xorl %ebx,%ebx
incl %ebx
movl $hw,%ecx
movl $hw_e,%edx
int $0x80
xorl %eax,%eax
ret
.data
hw:
.string "Hello world!\012"
hw_e = . - hw
######################
Сохраните исходный код библиотеки в файле static2.s
Это AT&T наречие Assembler'а.
.globl my_printf - "my_printf" описывается как глобальная (видимая в других объектных файлах) последовательность
my_printf: - начало описание функции my_printf
movl $4,%eax - поместим 4 в eax (4 - номер системного вызова write)
xorl %ebx,%ebx и incl %ebx - поместим в ebx единицу - номер STDOUT
movl $message,%ecx - в ecx запишем адрес начала сообщения
movl $message_l,%edx - в edx поместим адрес конца сообщения
int $0x80 - произведем системный вызов write
xorl %eax,%eax - в eax - код возврата (0)
ret - вернемся в вызывающую процедуру
.data - секция данных (разумеется, мы могли бы передавать выводимую строку как параметр, но тогда вычисление ее конца потребовало бы от нас дополнительных усилий, что, согласитесь, лениво :-) )
Теперь получим библиотеку:
gcc -c static2.s -o static2.o
ar rc static2.a static2.o
ranlib static2.a
На выходе имеем статическую библиотеку static2.a
Теперь напишем программу, использующую эту статическую библиотеку (язык C):
######################
#include
int my_printf();
int main()
{
int x = my_printf();
return 0;
}
######################
Сохраните текст программы в файле program3.c
Заметьте, я добавил прототип библиотечной функции для удобства.
Скомпилируем и слинкуем программу с библиотекой, после чего запустим программу на выполнение:
gcc program3.c static2.a
./a.out
На выходе получим:
Hello world!
* Принцип линкования статических библиотек с программами на Assembler'е аналогичен принципу для программ на C. Просто, когда будете использовать статические библиотеки в Assembler'е, помните о соглашениях C по передаче аргументов в функцию и возвращению результата.
4) Статические библиотеки на языке C++.
Принцип создания аналогичен статическим библиотекам на C, но перед каждой экспортируемой функцией не забывайте добавлять:
extern "C"
(экспортировать как функцию на C - т.е. без расширения имен).
* Кстати, используйте g++ вместо gcc, если захотите протестировать приведенные выше примеры.
Подключение к вашей программе аналогично подключению к программе, написанной на C, за исключением необходимости явно добавлять к тексту программы прототипы импортируемых функций в следующем виде:
extern "C" PROTOTYPE
Где PROTOTYPE - прототип импортируемой функции.
* При подключении статических библиотек на C++ к программе на C сопряжено с некоторыми трудностями - т.к. при компиляции и линковки программы необходимо будет также вручную подключить системные библиотеки для реализации функционала, предоставляемого библиотекой Standart C++ сверх того, что предоставляет библиотека Standart C.
----------------------------------------------------------------------------------------------------------------
link
Комментариев нет:
Отправить комментарий