2010-07-01 5 views
5

Мое первое сообщение на этом сайте с огромной надеждой :: Я пытаюсь понять статические ссылки, динамические ссылки, общие библиотеки, статические библиотеки и т. Д., С gcc. Каждый раз, когда я пытаюсь вникать в эту тему, у меня есть кое-что, что я не совсем понимаю.в gcc Как заставить разрешение символа во время выполнения

Некоторые практические работы:

bash$ cat main.c 

#include "printhello.h" 
#include "printbye.h" 

void main() 
{ 
PrintHello(); 
PrintBye(); 
} 

bash$ cat printhello.h 
void PrintHello(); 

bash$ cat printbye.h 
void PrintBye(); 

bash$ cat printbye.c 
#include <stdio.h> 

void PrintBye() 
{ 
printf("Bye bye\n"); 
} 

bash$ cat printhello.c 
#include <stdio.h> 

void PrintHello() 
{ 
printf("Hello World\n"); 
} 

gcc -Wall -fPIC -c *.c -I. 
gcc -shared -Wl,-soname,libcgreet.so.1 -o libcgreet.so.1.0 *.o 
ln -sf libcgreet.so.1.0 libcgreet.so 
ln -sf libcgreet.so.1.0 libcgreet.so.1 

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

gcc -Wall -L. main.c -lcgreet -o greet

Это очень хорошо работает, и если я установить LD_LIBRARY_PATH перед запуском приветствовать (или связать его с опцией RPATH) я могу заставить его работать.

Мой вопрос, однако, различен: Поскольку я все равно использую общую библиотеку, невозможно ли принудительное разрешение символа во время выполнения (не уверены в терминологии, но, возможно, называются динамическими связями в соответствии с книгой «Линкеры и загрузчики») , Я понимаю, что мы не хотим этого делать, потому что это заставляет программу работать медленно и имеет накладные расходы каждый раз, когда мы хотим запустить программу, но я пытаюсь понять это, чтобы очистить мои концепции.

Обеспечивает ли gcc-компоновщик любую возможность задержки разрешения символов во время выполнения? (чтобы сделать это с помощью библиотеки, на которой мы на самом деле будем запускать программу) (поскольку библиотека, доступная во время компиляции, может отличаться от той, которая доступна во время выполнения, если какие-либо изменения в библиотеке) Я хочу быть в состоянии сделать так :

bash $ gcc main.c -I.

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

Спасибо, Ученик навсегда.

+0

http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html – adf88

+0

Убедитесь, что вы пометили вопрос на соответствующем языке. Он помечен как C++, но код C. Обратите внимание, что для возможности использования чистой динамической библиотеки для загрузки кода на C++ необходимо будет содержать лишний «extern» C «разбрызганный вокруг, который не нужен и не действителен в C. –

ответ

9

Любой линкер (gcc, ld или любой другой) разрешает только ссылки во время компиляции. Это потому, что стандарт ELF (как и большинство других) не определяет привязку времени выполнения во время описания. Они либо связывают статически (например, lib.a), либо во время запуска (lib.so, которое должно присутствовать при загрузке ELF). Однако, если вы используете динамическую ссылку, компоновщик будет только помещать в ELF имя файла и символы, которые он должен найти, он не связывает файл напрямую. Итак, если вы хотите позже обновить lib до более новой версии, вы можете сделать это, пока система может найти одно и то же имя файла (путь может быть другим) и одинаковые имена символов.

Другой вариант, чтобы получить символы во время выполнения, заключается в использовании dlopen, который не имеет ничего общего с gcc или ld. dlopen просто введите, откроется динамическая библиотека ссылок, как и fopen, и вернет вам дескриптор, который затем перейдет к dlsym с именем нужного символа, который может быть именем функции, например. dlsym затем передаст вам указатель на этот символ, который затем можно использовать для вызова функции или использования в качестве переменной. Так реализуются плагины.

+0

+1 для приятного ответа и указания плагинов. – stinky472

+1

В случае правильного тега языка C++ не забудьте пометить символы как «extern» C «", чтобы они не искажались во время компиляции. –

1

Я думаю, что вы ищете вариант ld '- unresolved-symbols = ignore-all', да, он может это сделать (игнорировать предыдущий ответ).Представьте себе сценарий, когда библиотека, загруженная позже (когда программа уже запущена), может использовать все символы, которые уже разрешены/загружены основным процессом, не нужно беспокоиться о том, чтобы сделать это снова. btw это не нервно делает его медленным, по крайней мере, на Linux

Смежные вопросы