Общие библиотеки и.H-файлы

У меня есть некоторые сомнения о том, как программы используют общую библиотеку.

когда я создаю общую библиотеку (с коммутаторами-shared-fPIC), я делаю некоторые функции доступными из внешней программы. Обычно я делаю dlopen() для загрузки библиотеки, а затем dlsym (), чтобы связать указанные функции с некоторыми указателями функций. Этот подход не предполагает включения каких-либо .H-файл. Есть ли способ избежать выполнения dlopen () & dlsym () и просто включить .h общей библиотеки?

I Угадай это может быть, как программы c++ использует код, хранящийся в общей библиотеке системы. т. е. просто включая stdlib.ч. и т. д.

4 ответов


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

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

когда вы gcc -c program.c, вы компилируете, и вы генерируете program.o. Этот шаг, где заголовки вопрос. Вам нужно #include <stdlib.h> на program.c на (например) использовать malloc и free. (Аналогично вам нужно #include <dlfcn.h> на dlopen и dlsym.) Если вы этого не сделаете, компилятор будет жаловаться, что он не знает, что эти имена есть, и остановитесь с ошибкой. Но если вы это сделаете #include заголовок компилятор не вставьте код вызываемой функции в program.o. Он просто вставляет ссылка для них. Причина в том, чтобы избежать дублирования кода: код должен быть доступен только один раз каждой частью вашей программы, поэтому, если вам нужны дополнительные файлы (module1.c, module2.c и так далее), Даже если они все используется malloc вы просто закончите со многими ссылками на одну копию malloc. Этот единственный экземпляр присутствует в стандарте библиотека в общей или статической форме (libc.so или libc.a) но они не упоминаются в вашем источнике, и компилятор не знает о них.

компоновщик is. На этапе связывания вы делаете gcc -o program program.o. Затем компоновщик будет искать все библиотеки, которые вы передаете в командной строке, и найдет один определение всех вызываемые вами функции, которые не определены в вашем собственном коде. Вот что такое -l делает (как объяснили другие): сообщите компоновщику список библиотек, которые вам нужно использовать. Их имена часто имеют мало общего с заголовками, которые вы использовали в предыдущем шаге. Например, чтобы использовать dlsym вам нужно libdl.so или libdl.a, так что ваша командная строка будет gcc -o program program.o -ldl. Использовать malloc или большинство функций в std*.h заголовки нужно libc, но потому что эта библиотека используется by каждый C программа это автоматически связан (как если бы вы сделали -lc).

Извините, если я буду вдаваться в подробности, но если вы не знаете разницы, вы захотите. Очень трудно понять, как работает компиляция C, если вы этого не делаете.

и последнее: dlopen и dlsym не являются обычным методом связывания. Они используются для особых случаев, когда вы хотите динамически определить, какое поведение вы хотите на основе информация, которая по какой-либо причине доступна только во время выполнения. Если вы знаете, какие функции вы хотите вызвать во время компиляции (true в 99% случаев), вам не нужно использовать dl* функции.


вы можете связать общие библиотеки, такие как статические. Затем их ищут при запуске программы. На самом деле, по умолчанию-lxxx предпочтет libXXX.Итак, к libXXX.a.


вам нужно дать компоновщику соответствующие инструкции для связывания вашей общей библиотеки.

имена общих библиотек похожи на libNAME.Итак, поэтому для связывания вы должны использовать -lNAME

назовите это libmysharedlib.Итак, а затем свяжите свою основную программу как:

gcc -o myprogram myprogram.c -lmysharedlib 

если вы используете CMake чтобы построить свой проект, вы можете использовать

TARGET_LINK_LIBRARIES(targetname libraryname)

в:

TARGET_LINK_LIBRARIES(myprogram mylibrary)

чтобы создать библиотеку "mylibrary", вы можете использовать

ADD_LIBRARY(targetname sourceslist)

в:

ADD_LIBRARY(mylibrary ${mylibrary_SRCS})

кроме того, этот метод является кросс-платформенным (тогда как просто передача флагов в gcc не является).