dlclose, dlerror, dlopen, dlsym - программный интерфейс для динамически загружаемых библиотек
НАЗВАНИЕdlclose, dlerror, dlopen, dlsym - программный интерфейс
для динамически загружаемых библиотек
СИНТАКСИС
#include
void *dlopen(const char *filename, int flag);
const char *dlerror(void);
void *dlsym(void *handle, char *symbol);
int dlclose(void *handle);
Специальные символы: _init, _fini.
ОПИСАНИЕ
dlopen загружает динамическую библиотеку, имя которой
указано в строке filename, и возвращает прямой указатель
на начало динамической библиотеки. Если filename не
является полным именем файла (т.е. не начинается с "/"),
то файл ищется в следующих местах:
в разделенном двоеточием списке каталогов, в
переменной окружения пользователя LD_LIBRARY_PATH.
В списке библиотек, кэшированных в файле
/etc/ld.so.cache.
В /usr/lib и далее в /lib.
Если filename указывает на NULL, то возвращается указатель
на основную программу.
Внешние ссылки разрешаются при работе с библиотеками в
списке библиотечных зависимостей и любыми другими, которые
уже открыты с флагом RTLD_GLOBAL. Если исполняемый модуль
был собран с флагом "-rdynamic", его символьная
информация также используется для разрешения ссылок в
динамически загружаемых библиотеках.
Значение flag должно быть одним из двух: RTLD_LAZY,
подразумевающим разрешение неопределенных символов в виде
кода, содержащегося в исполняемой динамической библиотеке;
или RTLD_NOW, требующим разрешения всех неопределенных
символов перед возвратом их из dlopen и возвращающим
ошибку, если разрешение не может быть выполнено. Также
значение RTLD_GLOBAL может быть задано через OR вместе с
flag; в этом случае внешние символы, определенные в
библиотеке, будут доступны загруженным позже библиотекам.
Если библиотека экспортировала функцию, названную _init,
то ее код выполняется перед возвратом из dlopen. Если
одна и та же библиотека загружается дважды через dlopen(),
то возвращается один и тот же указатель. Библиотека dl
поддерживает счетчик ссылок, созданный для указателей на
файлы, так что динамическая библиотека не может быть
выгружена, пока не будет вызвана функция dlclose столько
раз, сколько необходимо для успешного выполнения функции
dlopen .
Если по какой-либо причине выполнение dlopen неудачно, то
она возвращает значение NULL. Понятный пользователю
текст, описывающий большинство ошибок, происходящих при
выполнении любых функций dl (dlopen, dlsym or dlclose),
может быть получен при помощи функции dlerror(). dlerror
возвращает NULL, если не возникло ошибок с момента
инициализации или его последнего вызова. Если вызывать
dlerror() дважды, то во второй раз результат выполнения
всегда будет равен NULL. dlsym использует указатель на
динамическую библиотеку, возвращаемую dlopen, и
оканчивающееся нулем символьное имя, а затем возвращает
адрес, указывающий, откуда загружается этот символ. Если
символ не найден, то возвращаемым значением dlsym является
NULL; тем не менее, правильным способом проверки dlsym на
наличие ошибок является сохранение в переменной результата
выполнения dlerror, а затем проверка, равно ли это
значение NULL. Это делается потому, что значение символа
действительно может быть NULL. Также необходимо сохранять
результат dlerror в переменной, поскольку если функция
dlerror вызвана еще раз, то возвращаемое ею значение будет
равно NULL.
Имеется две специальных псевдо-указателя динамической
библитеки RTLD_DEFAULT и RTLD_NEXT. Первый ищет требуемый
символ, используя порядок поиска библиотек по умолчанию.
Второй найдет функцию в следующей библиотеке в
соответствии с порядком поиска. Он полезен только при
использовании из динамической библиотеки. Это позволяет
реализовывать обертки (wrapper) вокруг функций из других
библиотек.
dlclose уменьшает на единицу счетчик ссылок на указатель
динамической библиотеки handle. Если нет других
загруженных библиотек, использующих ее символы и если
счетчик ссылок принимает нулевое значение, то динамическая
библиотека выгружается. Если динамическая библиотека
экпортировала функцию, названную _fini, то эта функция
вызывается перед выгрузкой библиотеки.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
dlclose возвращает 0 при удачном завершении и ненулевой
результат при ошибке.
ПРИМЕРЫ
Загрузка библиотеки math и вывод cosine (2.0):
int main(int argc, char **argv) {
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen ("/lib/libm.so", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
cosine = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fprintf (stderr, "%s\n", error);
exit(1);
}
printf ("%f\n", (*cosine)(2.0));
dlclose(handle);
}
Если этот скрипт находится в файле "foo.c", вы можете
собрать программу при помощи следующей команды:
gcc -rdynamic -o foo foo.c -ldl
БЛАГОДАРНОСТИ
Стандарт интерфейса dlopen взят из системы Solaris.
Реализация dlopen в Linux была написана Eric Youngdale при
участии Mitch D'Souza, David Engel, Hongjiu Lu, Andreas
Schwab и других. Страница руководства была написана Adam
Richter.