Возможно вы искали: 'Wild Wild West: Steel ...'

May 15 2025 19:12:26
  • Как сделать 8Gamers.Ru домашней страницей?
  • Игры
    • База данных по играх
    • Игровые новости
    • Игровая индустрия
    • Обзоры на игры
    • Прохождения игр
    • Гайды к играм
    • Превью о играх
    • Игровые тизеры
    • Игровые арты
    • Игровые обои
    • Игровые скриншоты
    • Игровые обложки
    • Игровые трейлеры
    • Игровое видео
    • Вышедшие игры
    • Ближайшие релизы игр
  • Кино и ТВ
    • База данных по кино
    • Статьи о кино
    • Постеры
    • Кадры из кино
    • Кино трейлеры
    • Сегодня в кино
    • Скоро в кино
  • Комиксы и манга
    • Манга по алфавиту
    • База данных по комиксах
    • Читать онлайн комиксы
    • Читать онлайн манга
    • База персонажей
  • Читы и коды
    • Чит-коды для PC игр
    • Чит-коды для консольных игр
    • Трейнеры
    • Коды Game Genie
  • Моддинг
    • Модификации
    • Карты к играм
    • Программы для моддинга
    • Статьи о моддинге
  • Геймдев
    • Всё о создании игр
    • Список движков
    • Утилиты в помощь игроделу
    • Конструкторы игр
    • Игровые движки
    • Библиотеки разработки
    • 3D-модели
    • Спрайты и тайлы
    • Музыка и звуки
    • Текстуры и фоны
  • Рецензии
    • Игры
    • Кино
    • Аниме
    • Комиксы
    • Мангу
    • Саундтреки
  • Саундтреки
    • Лирика
  • Файлы
    • Патчи к играм
    • Русификаторы к играм
    • Сохранения к играм
    • Субтитры к кино
  • Медиа
    • Видео
    • Фото
    • Аудио
    • Фан-арты
    • Косплей
    • Фото с виставок
    • Девушки из игр
    • Рисунки
    • Рисуем онлайн
    • Фотохостинг
  • Юмор
    • Анекдоты
    • Афоризмы
    • Истории
    • Стишки и эпиграммы
    • Тосты
    • Цитаты
  • Флеш
    • Азартные
    • Аркады
    • Бродилки
    • Гонки
    • Для девочек
    • Для мальчиков
    • Драки
    • Квесты
    • Леталки
    • Логические
    • Мультфильмы
    • Открытки
    • Приколы
    • Разное
    • Спорт
    • Стратегии
    • Стрелялки
Статистика

Статей: 87772
Просмотров: 96111483
Игры
Injustice:  Gods Among Us
Injustice: Gods Among Us
...
Dark Souls 2
Dark Souls 2
Dark Souls II - вторая часть самой хардкорной ролевой игры 2011-2012 года, с новым героем, сюжето...
Battlefield 4
Battlefield 4
Battlefield 4 - продолжение венценосного мультиплеер-ориентированного шутера от первого ли...
Кино
Steins;Gate
Steins;Gate
Любители японской анимации уже давно поняли ,что аниме сериалы могут дать порой гораздо больше пи...
Ку! Кин-дза-дза
Ку! Кин-дза-дза
Начинающий диджей Толик и всемирно известный виолончелист Владимир Чижов встречают на шумной моск...
Обзоры на игры
• Обзор Ibara [PCB/PS2] 18357
• Обзор The Walking ... 18801
• Обзор DMC: Devil M... 19879
• Обзор на игру Valk... 15877
• Обзор на игру Stars! 17764
• Обзор на Far Cry 3 17948
• Обзор на Resident ... 16024
• Обзор на Chivalry:... 17508
• Обзор на игру Kerb... 17981
• Обзор игры 007: Fr... 16619
Превью о играх
• Превью к игре Comp... 17960
• Превью о игре Mage... 14464
• Превью Incredible ... 14721
• Превью Firefall 13479
• Превью Dead Space 3 16334
• Превью о игре SimC... 14730
• Превью к игре Fuse 15442
• Превью Red Orche... 15542
• Превью Gothic 3 16343
• Превью Black & W... 17354
Главная » Статьи » Разное » Совместно используемые библиотеки в C под Linux для начинающих. (share lib gcc linux)

Совместно используемые библиотеки в C под Linux для начинающих. (share lib gcc linux)

Ключевые слова: share, lib, gcc, linux, (найти похожие документы)

From: LogRus <logrusadm@pisem.net>
Date: Mon, 25 Dec 2003 14:31:37 +0000 (UTC)
Subject: Совместно используемые библиотеки в C под Linux для начинающих.

Оригинал: http://club.shelek.com/viewart.php?id=106


Совместно используемые библиотеки в C под Linux для начинающих.

Для начала напишем два файлика test.c и app.c
Листинг test.c
---------------------------------------------------
int f()
{
return 3;
}
---------------------------------------------------

Листинг app.c
--------------------------------------------------
int main()
{
return f();
}
--------------------------------------------------

Конечно можно всё сразу собрать и всё зарабоет. Но мы пойдем другим
путём берём компилируем test.c в test.o.

$ gcc -c -o test.o test.c

Опция -c значит скомпилировать не соберая. Теперь делаем из test.o
библиотечку статическую. Выполняем вот эту команду.

$ ar cr libtest.a test.o test1.o test2.o

Файлы test1.o и test2.o я вписал просто показать, что можно собрать
некий архив объектных файлов ("архив" это второе название статической
библиотеки). Заметьте, что у слова тест появился префикс lib и
окончание поменяли с .o на .a . Команда опции команды ar означают: c
не ругатся если надо создать файл; r запихать в архив файлы или
заменить существующие.

Попробуем это всё собрать.

$ gcc -c -o app.o app.c
$ gcc -o app -L. -ltest app.o

app.o(.text+0x11): In function 'main':
: undefined reference to 'f'
collect2: ld returned. 1 exit status

Спрашиваете, что буквально за фигня. Отвечаю: компоновщик смотрит свои
параметры слева на право и когда он доходит до app.o он "думает", что
libtest.a ему нафиг не нужна никто её не пользует, отсюды вывод надо
поставить app.o сразу после app и всё заработает. Проверяем.

$ gcc -o app app.o -L. -ltest

Работает. Далее надо проверить работает ли наш файлик app который мы
собрали.

$ ./app
$ echo $?
3
$

Работает, как не странно! Опять на счет опций -L. значит искать
библиотеки сначала в директории указанной после -L в нашем случае у
нас стоит там точка значит в дериктории. где мы находимся. Опция
-ltest как раз и значит использовать библиотеку libtest.

С этим надеюсь ясно. Тепер переходим к совместно используемым
библиотекам(динамически подключаемым). Эти библиотеки похожы на
архивы, но гдавное отличие в том, что вместо кода из библиотеки в
программу включается ссылка на библиотеку.

Для создания библиотеки составляющие её файлы надо собрать использую
опцию -fPIC (Position-Independent Code):

$ gcc -c -fPIC test.c

Теперь соберём библиотеку:

$ gcc -shared -fPIC -o libtest.so test.o test1.o test2.o

Опция -shared заставляет компоновщик создать именно совместно
используемую библиотеку. Заново собераем нашу программу:

$ gcc -o app app.o -L. -ltest

Теперь выполним команду:

$ ldd app
libtest.so => not found
libc.so.6 => /lib/tls/libc.so.6 (0x42000000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

Эта команда нам показывает используемые библиотеки. Как видите нашу
библиотечку программа не нашла. А всё потому что в файл помещается
только имя библиотеки, а не путь к ней и при запуске библиотека ищется
только в стандартных каталогах /lib и /usr/lib. При попытке запустить
программу получаем сообщение о том, что не найдена библиотека. Первое
решение проблемы установить переменную окружения LD_LIBRARY_PATH

$ export LD_LIBRARY_PATH=/home/logrus/Documents/test:/usr/local/lib

Выполнив эту команду мы сообщили ситеме, что библиотеки могут хранится
еще и в директориях /home/logrus/Documents/test и /usr/local/lib .
Другое решение использование при компиляции опции -Wl,-rpath примерно
так:

$ gcc -o app app.o -L. -ltest -Wl,-rpath,/home/logrus/Documents/test

В этом случае в вашем приложении будет прописан полный путь до
библиотеки.

У вас наверняка возник вопрос, а что, если у меня есть оба вариата
библиотеки и .a и .so? В этом случае если компоновщик обнаруживает обе
библиотеки, то он выберет динамическую, если не указано иначе. Иначе
это использовать опцию -static.

Рекомендую всё это срочно протестировать! Набавать текста не много.

Если вам захочится использовать математические функции, которые не
входят в состав libc (стандартаня библиотека C) автоматически
подключаемой к вашей программе (это если вы этого не заметили в
результатах работы комады ldd), то компилируем так:

# gcc -o compute compute.c -lm

При компоновке програм на C++ к вашей программе подключается
библиотека libstdc++.

Часто библиотеки связаны между собой.

Например соберем такую штуку:
Листинг testtiff.c
----------------------------------------------------------------------
#include <stdio.h>
#include <tiffio.h>
int main (int argc, char** argv)
{
TIFF* tiff;
tiff = TIFFOpen (argv[1], "r");
TIFFClose(tiff);
return 0;
}
----------------------------------------------------------------------

При компилляции используем флаг -ltiff

$ gcc -o tifftest tifftest.c -ltiff

Посмотрим что нам выдаст ldd

$ ldd tifftest

libtiff.so.3 => /usr/lib/libtiff.so.3 (0x40022000)
libc.so.6 => /lib/tls/libc.so.6 (0x42000000)
libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x40063000)
libz.so.1 => /usr/lib/libz.so.1 (0x40082000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

Это говорит нам о том, что динимические библиотеки зависят от друг
друга и что эти библиотеки также подключены. Посмотри и запешите или
запомните разменр исполняемого файла tifftest.

Соберем его со статическими библиотеками.

$ gcc -static -o tifftest tifftest.c -ltiff

/usr/local/lib/libtiff.a(tif_luv.o)(.text+0xf74): In function `LogL16toY':
../libtiff/tif_luv.c:657: undefined reference to `exp'
/usr/local/lib/libtiff.a(tif_luv.o)(.text+0x1014): In function `LogL16fromY':
../libtiff/tif_luv.c:672: undefined reference to `log'
/usr/local/lib/libtiff.a(tif_luv.o)(.text+0x1036):../libtiff/tif_luv.c
:672: undefined reference to `log'
/usr/local/lib/libtiff.a(tif_luv.o)(.text+0x10b8):../libtiff/tif_luv.c
:674: undefined reference to `log'
/usr/local/lib/libtiff.a(tif_luv.o)(.text+0x10e8):../libtiff/tif_luv.c
:674: undefined reference to `log'
/usr/local/lib/libtiff.a(tif_luv.o)(.text+0x1467): In function `LogL10toY':
../libtiff/tif_luv.c:736: undefined reference to `exp'
/usr/local/lib/libtiff.a(tif_luv.o)(.text+0x14cd): In function `LogL10fromY':
../libtiff/tif_luv.c:750: undefined reference to `log'
/usr/local/lib/libtiff.a(tif_luv.o)(.text+0x14ef):../libtiff/tif_luv.c
:750: undefined reference to `log'
collect2: ld returned 1 exit status

Ну как красиво? Это из-за того, что статические библиотеки не могут
ссылаться друг на друга. Значит нам надо вручною указать все
необходимые библиотеки.

$ gcc -static -o tifftest tifftest.c -ltiff -ljpeg -lz -lm

Проверьте размер исполняемого файла. Ну как впечатляет? Проверьте
подключеныль динамические библиотеки.
И на последок. Допустим есть ситуация когда библиотеки циклически
зависят друг от друга, т.е. libtest1.a зависит от libtest2.a, а
libtest2.a зависит от libtest1.a тогда просто следует сделать например
так:

$ gcc -o app app.o -ltest1 -ltest2 -ltest1

Пока всё! ;)


ЧАСТЬ 2.

Иногда требуется загрузить какую нибуть библиотеку я вно не компануя
её. Например страшное слово плагин. Для этих целей у нас есть dlopen,
dlclose, dlsym и dlerror объявленны в dlfcn.h, компилируется с флагом -ldl.

void *dlopen(const char *filename, int flag);
const char *dlerror(void);
void *dlsym(void *handle, char *symbol);
int dlclose(void *handle);

Функция dlopen открывает файл filename с флагами flag. Вернее
откравает она его в том случае, если он еще небыл кем-то открыт в этом
случае она увеличивет счетчик ссылок возврашает дискриптор библиотеки.

Путь к библиотеки можно не указывать, тогда бибилиотека ищется .
dlclose совершает обратную работу уменьшает счетчик и закрывает
библиотеку, если её больше не использует.
Функция dlsys возврашает указатель на функцию или переменную с именем
symbol для библиотеки Handle.

Функция dlerror возвращает струказатель на строку с описанием ошибки.
Пример:

void * handle = dlopen("mylib.so", RTLD_LAZY);
void (* test)() = dlsym( handle, "myfunc");
(* test)();
dlclose(handle);

Если библиотека пишется на C++ имеет смысл объявить обще доступные
функции со спецификатором extern "C".

extern "C" void my_func();

Это делается из-за того, что компилятор C++ имеет свойство подменять
имена функций своими именами в которых закодированна информация о
функции.

Пример:

Листинг testdl.c:
------------------------------------------------------------
#include <stdio.h>
#include <dlfcn.h>
int main(int argc,char** argv[])
{
/* Проверяем кол-во параметров.
Если чего не так выводим сообщение об ошибке и уходим. */
if (argc<2) {
fprintf(stderr,"Usage: %s libnamen",argv[0]);
exit(1);
}
/* Пытаемся загрузить библиотеку. */
printf("Try to load library %sn",argv[1]);
void * handle = dlopen(argv[1], RTLD_LAZY);
/* Если чего не так выводим сообщение об ошибке и уходим. */
if (handle == NULL) {
fprintf(stderr,"%s",dlerror());
exit(2);
}
printf("Ok! Loaded!n");
/* Пытаемся загрузить функцию библиотеки. */
void (*libfunc)(int) = dlsym(handle, "libfunc");
/* Если чего не так выводим сообщение об ошибке и уходим. */
if (libfunc == NULL) {
fprintf(stderr,"%sn",dlerror());
exit(3);
}
/* Выводим название загруженной библиотеки. */
printf("Loaded library: %s nLib output:n",argv[1]);
/* Вызываем функцию из библиотеки передаем при этом дискриптор
для вывода данных. */
libfunc(stderr);
/* Закрываем библиотеку. */
dlclose(handle);
return 0;
}

------------------------------------------------------------
Листинг mygettime.c:
------------------------------------------------------------
#include <sys/time.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
void libfunc(int fd)
{
struct timeval tv;
struct tm* ptm;
char * time_string[40];
/* Получаем локальное время. */
gettimeofday(&tv, NULL);
ptm = localtime(&tv.tv_sec);
/* Преобразуем в строку. */
strftime(time_string, sizeof(time_string), "%H:%M:%S", ptm);
/* Выводим время. */
fprintf(fd,"Local time: %sn",time_string);
return;
}

------------------------------------------------------------
Листинг myversion.c:
------------------------------------------------------------
#include <fcntl.h>
void libfunc(int fd)
{
int in_fd;
int rval;
char *buffer=calloc(512,sizeof(char));
/* Открываем файл /etc/issue. */
in_fd = open("/etc/issue",O_RDONLY);
if(in_fd == -1) {
fprintf(fd,"Error open /etc/issuen");
exit(1);
}
/* Читаем из /etc/issue и пишем в fd. */
while ((rval=read(in_fd,buffer,512))!= 0)
fprintf(fd,"%s",buffer);
return;
}

------------------------------------------------------------
Листинг Makefile:
------------------------------------------------------------
### Конфигурация. ###################################
SOURCES = testdl.c
MODULES = mygettime.so myversion.so
### Правила. ########################################
# Служебный целевой модуль
.PHONY: all clean
# Стандартный целевой модуль: компиляция всех фалов.
all: $(MODULES) testdl
# Удаление всего чего насобирали.
clean:
rm -f $(MODULES) testdl
# Собираем гвавный файл.
testdl: $(SOURCES)
$(CC) $(CFLAGS) -Wl,-export-dynamic -o $@ $^ -ldl
# Собираем библиотеки.
$(MODULES):
%.so: %.c
$(CC) $(CFLAGS) -fPIC -shared -o $@ $<
------------------------------------------------------------

С файлами надеюсь всё понятно. Testdl.c наша главная программа которая
будет использовать наши библиотечки. Файл mygettime.c и myversion.c
файлы для библиотек выводят текушее время и версию системы. Makefile
это, что бы нам руками всё время команды не писать для компиляции, а
набрали make и всё собралось, набрали make clean и всё собраное
удалилось.

По тестируем всё это:

$ make
$ export LD_LIBRARY_PATH=/path_to_current_dir
$ ./testdl mygettime.so && ./testdl myversion.so

Try to load library mygettime.so
Ok! Loaded!
Loaded library: mygettime.so
Lib output:
Local time: 09:44:00
Try to load library myversion.so
Ok! Loaded!
Loaded library: myversion.so
Lib output:
ASPLinux release 9 (Ural)
Kernel 2.4.20-9asp on an i686

Спрашивается, на зачем мы передавали в функции stderr, если всё равно
идет вывод на экран. а мы за одно посмотрим как перенаправить поток.

Есть три стандартаных дескриптора файлов это 0, 1, 2 или stdin,
stdout, stderr. Перенаправим в файлик test.log стандартный вывод
ошибок.

$ ./testdl myversion.so 2>test.log
Try to load library myversion.so
Ok! Loaded!
Loaded library: myversion.so
Lib output:

$ cat test.log
ASPLinux release 9 (Ural)
Kernel 2.4.20-9asp on an i686
$

Спрашивается. а зачем. Ну даже не знаю. Можно например запустить две
программы терминала в графическом режиме. Затем в одной запустить
другую программу например компиляцию чего-нибуть и перенаправить вывод
ощибок в другое окно, чтобы не путались сообщения об ошибках и
сообщения о ходе выполнения. Или в файли можно лог ошибок сохранить.

Да малоли чего. Пример

$ echo "Hi, everybody." >>/dev/pts/1
или
$ make 2>test.log 1>/dev/pts/1

Всё!
1217 Прочтений •  [Совместно используемые библиотеки в C под Linux для начинающих. (share lib gcc linux)] [08.05.2012] [Комментариев: 0]
Добавил: Ukraine Vova
Ссылки
HTML: 
[BB Url]: 
Похожие статьи
Название Добавил Добавлено
• Совместно используемые библиотеки в... Ukraine Vova 08.05.2012
Ни одного комментария? Будешь первым :).
Пожалуйста, авторизуйтесь для добавления комментария.

Проект входит в сеть сайтов «8Gamers Network»

Все права сохранены. 8Gamers.NET © 2011 - 2025

Статьи
Рецензия на Pressure
Рецензия на Pressure
Чтобы обратить на себя внимание, начинающие маленькие разработчики, как правило, уходят в жанры, ...
Рецензия на Lost Chronicles of Zerzura
Рецензия на Lost Chron...
Игры, сделанные без любви и старания, похожи на воздушный шар – оболочка есть, а внутри пусто. Lo...
Рецензия на The Bridge
Рецензия на The Bridge
«Верх» и «низ» в The Bridge — понятия относительные. Прогуливаясь под аркой, можно запросто перей...
Рецензия на SimCity
Рецензия на SimCity
Когда месяц назад состоялся релиз SimCity, по Сети прокатилось цунами народного гнева – глупые ош...
Рецензия на Strategy & Tactics: World War 2
Рецензия на Strategy &...
Название Strategy & Tactics: World War II вряд ли кому-то знакомо. Зато одного взгляда на ее скри...
Рецензия на игру Scribblenauts Unlimited
Рецензия на игру Scrib...
По сложившейся традиции в информационной карточке игры мы приводим в пример несколько похожих игр...
Рецензия на игру Walking Dead: Survival Instinct, The
Рецензия на игру Walki...
Зомби и продукция-по-лицензии — которые и сами по себе не лучшие представители игровой биосферы —...
Обратная связь | RSS | Донейт | Статистика | Команда | Техническая поддержка