Общие библиотеки и.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 не является).