DynaLoader
СОДЕРЖАНИЕ
НАЗВАНИЕ
DynaLoader - Динамическая загрузка библиотек C в Perl-код
СИНТАКСИС
package YourPackage;
require DynaLoader;
@ISA = qw(... DynaLoader ...);
__PACKAGE__->bootstrap;
# optional method for 'global' loading
sub dl_load_flags { 0x01 } ОПИСАНИЕ
Этот документ определяет стандартный универсальный интерфейс к механизмам динамической компоновки, доступным на многих платформах. Его основная цель - реализовать автоматическую динамическую загрузку Perl-модулей.
Этот документ служит как спецификацией для тех, кто хочет реализовать DynaLoader для новой платформы, так и руководством для тех, кто хочет использовать DynaLoader непосредственно в приложении.
DynaLoader разработан как очень простой высокоуровневый интерфейс, достаточно общий, чтобы охватить потребности SunOS, HP-UX, Linux, VMS и других платформ.
Также надеется, что интерфейс покроет потребности OS/2, NT и т. д., а также позволит псевдодинамическую компоновку (используя ld -A во время выполнения).
Следует подчеркнуть, что DynaLoader сам по себе практически бесполезен для доступа к библиотекам, не относящимся к Perl, потому что он предоставляет почти никакой "склейки" Perl-C. Например, нет механизма для вызова функции библиотеки C или передачи аргументов. Модуль C::DynaLib доступен на сайтах CPAN и выполняет эту функцию для некоторых распространённых типов систем. А с 2000 года также есть Inline::C, модуль, который позволяет писать Perl-подпрограммы на C. Также доступен на вашем локальном сайте CPAN.
Резюме интерфейса DynaLoader
@dl_library_path
@dl_resolve_using
@dl_require_symbols
$dl_debug
$dl_dlext
@dl_librefs
@dl_modules
@dl_shared_objects
Implemented in:
bootstrap($modulename) Perl
@filepaths = dl_findfile(@names) Perl
$flags = $modulename->dl_load_flags Perl
$symref = dl_find_symbol_anywhere($symbol) Perl
$libref = dl_load_file($filename, $flags) C
$status = dl_unload_file($libref) C
$symref = dl_find_symbol($libref, $symbol) C
@symbols = dl_undef_symbols() C
dl_install_xsub($name, $symref [, $filename]) C
$message = dl_error C - @dl_library_path
-
Стандартный/по умолчанию список каталогов, в которых dl_findfile() будет искать библиотеки и т. д. Каталоги просматриваются в порядке: $dl_library_path[0], [1] и т. д.
@dl_library_path инициализируется списком «обычных» каталогов (/usr/lib и т. д.), определенных Configure (
$Config{'libpth'}). Это должно обеспечить переносимость на широком спектре платформ.@dl_library_path также должен быть инициализирован любыми другими каталогами, которые могут быть определены из среды во время выполнения (например, LD_LIBRARY_PATH для SunOS).
После инициализации @dl_library_path может быть изменён приложением с помощью push и unshift перед вызовом dl_findfile(). Unshift может использоваться для добавления каталогов в начало порядка поиска, чтобы сэкономить время поиска или переопределить библиотеки с одинаковым именем в «обычных» каталогах.
Функция загрузки, которую вызывает dl_load_file(), может потребовать абсолютный путь. Функция dl_findfile() и @dl_library_path могут использоваться для поиска и возврата абсолютного пути к библиотеке/объекту, которую вы хотите загрузить.
- @dl_resolve_using
-
Список дополнительных библиотек или других общих объектов, которые могут использоваться для разрешения любых неопределённых символов, которые могут быть сгенерированы последующим вызовом load_file().
Это необходимо только на некоторых платформах, которые не обрабатывают зависимые библиотеки автоматически. Например, библиотека расширения Perl Socket (auto/Socket/Socket.so) содержит ссылки на многие функции сокетов, которые необходимо разрешить при её загрузке. Большинство платформ автоматически знают, где найти зависимую библиотеку (например, /usr/lib/libsocket.so). Несколько платформ нуждаются в явном указании расположения зависимой библиотеки. Используйте @dl_resolve_using для этого.
Пример использования:
@dl_resolve_using = dl_findfile('-lsocket'); - @dl_require_symbols
-
Список одного или более имён символов, которые находятся в файле библиотеки/объекта, который нужно динамически загрузить. Это необходимо только на некоторых платформах.
- @dl_librefs
-
Массив дескрипторов, возвращённых успешными вызовами dl_load_file(), выполненными bootstrap, в порядке их загрузки. Может использоваться с dl_find_symbol() для поиска символа в любом из загруженных файлов.
- @dl_modules
-
Массив имён модулей (пакетов), которые были bootstrap'ed.
-
Массив имён файлов общих объектов, которые были загружены.
- dl_error()
-
Синтаксис:
$message = dl_error();Текст сообщения об ошибке от последней неудачной функции DynaLoader. Обратите внимание, что, подобно errno в Unix, успешный вызов функции не сбрасывает это сообщение.
Реализации должны обнаруживать ошибку, как только она произойдёт в любой из других функций, и сохранять соответствующее сообщение для последующего извлечения. Это позволит избежать проблем на некоторых платформах (например, SunOS), где сообщение об ошибке очень временное (например, dlerror()).
- $dl_debug
-
Внутренние сообщения отладки включены, когда $dl_debug имеет значение true. В настоящее время установка $dl_debug влияет только на Perl-сторону DynaLoader. Эти сообщения должны помочь разработчику приложения в решении любых проблем, связанных с использованием DynaLoader.
$dl_debug устанавливается в
$ENV{'PERL_DL_DEBUG'}если определён.Для разработчика/портирующего DynaLoader существует аналогичная переменная отладки, добавленная в код C (см. dlutils.c) и включённая, если Perl был скомпилирован со флагом -DDEBUGGING. Это также может быть установлено через переменную среды PERL_DL_DEBUG. Установите значение 1 для минимальной информации или большее значение для большей информации.
- $dl_dlext
-
При указании (локализованном) в файле .pm модуля указывает расширение, которое будет иметь загружаемый объект модуля. Например:
local $DynaLoader::dl_dlext = 'unusual_ext';указывает, что загружаемый объект модуля имеет расширение
unusual_extвместо более обычного$Config{dlext}. ПРИМЕЧАНИЕ: это также требует, чтобы Makefile.PL модуля указал (вWriteMakefile()):DLEXT => 'unusual_ext', - dl_findfile()
-
Синтаксис:
@filepaths = dl_findfile(@names)Определяет полные пути (включая расширение файла) одного или нескольких загружаемых файлов по их общим именам и, необязательно, по одному или нескольким каталогам. По умолчанию ищет каталоги в @dl_library_path и возвращает пустой список, если файлы не найдены.
Имена могут быть указаны в различных независимых от платформы форматах. Любые имена в форме -lname преобразуются в libname.*, где .* — подходящее расширение для платформы.
Если имя ещё не имеет подходящего префикса и/или суффикса, то соответствующий файл будет искаться путём перебора комбинаций префикса и суффикса, подходящих для платформы: "$name.o", "lib$name.*" и "$name".
Если в @names включены каталоги, они просматриваются перед @dl_library_path. Каталоги могут быть указаны как -Ldir. Все остальные имена рассматриваются как имена файлов, которые нужно найти.
Использование аргументов в форме
-Ldirи-lnameрекомендуется.Пример:
@dl_resolve_using = dl_findfile(qw(-L/usr/5lib -lposix)); - dl_expandspec()
-
Синтаксис:
$filepath = dl_expandspec($spec)Некоторые необычные системы, такие как VMS, требуют специальной обработки имён файлов для обработки символических имён файлов (например, логических имён VMS).
Для поддержки этих систем функция dl_expandspec() может быть реализована либо в файле dl_*.xs, либо код может быть добавлен в функцию dl_expandspec() в DynaLoader.pm. См. DynaLoader_pm.PL для получения дополнительной информации.
- dl_load_file()
-
Синтаксис:
$libref = dl_load_file($filename, $flags)Динамически загружает $filename, который должен быть путём к общему объекту или библиотеке. Возвращает некий «дескриптор библиотеки» в качестве дескриптора загруженного объекта. Возвращает undef при ошибке.
Аргумент $flags изменяет поведение dl_load_file. Назначенные биты:
0x01 make symbols available for linking later dl_load_file's. (only known to work on Solaris 2 using dlopen(RTLD_GLOBAL)) (ignored under VMS; this is a normal part of image linking)(На системах, которые предоставляют дескриптор загруженного объекта, таких как SunOS и HPUX, $libref будет этим дескриптором. На других системах $libref обычно будет $filename или указатель на буфер, содержащий $filename. Приложение не должно просматривать или изменять $libref каким-либо образом.)
Это функция, которая выполняет основную работу. Она должна использовать текущие значения @dl_require_symbols и @dl_resolve_using, если это необходимо.
SunOS: dlopen($filename) HP-UX: shl_load($filename) Linux: dld_create_reference(@dl_require_symbols); dld_link($filename) VMS: lib$find_image_symbol($filename,$dl_require_symbols[0])(Функция dlopen() также используется Solaris и некоторыми версиями Linux и является распространённым выбором при предоставлении «обёртки» на других механизмах, как это делается в порте OS/2.)
- dl_unload_file()
-
Синтаксис:
$status = dl_unload_file($libref)Динамически разгружает $libref, который должен быть неким «дескриптором библиотеки», как возвращается dl_load_file. Возвращает 1 при успехе и 0 при ошибке. Эта функция необязательна и может не предоставляться на всех платформах.
Если она определена и Perl скомпилирован с определённым C-макросом
DL_UNLOAD_ALL_AT_EXIT, то она вызывается автоматически при выходе интерпретатора для каждого общего объекта или библиотеки, загруженной DynaLoader::bootstrap. Все такие дескрипторы библиотек хранятся в @dl_librefs в DynaLoader::Bootstrap при загрузке библиотек. Файлы разгружаются в порядке «последний вошёл — первый вышел».Эта разгрузка обычно необходима при встраивании Perl общего объекта (например, одного, сконфигурированного с -Duseshrplib) в более крупное приложение, и интерпретатор Perl создаётся и уничтожается несколько раз в течение срока службы приложения. В этом случае возможно, что системный динамический связующий компонент разгрузит, а затем повторно загрузит общий libperl без перемещения любых ссылок на него из любых файлов, DynaLoaded предыдущей инкарнацией интерпретатора. В результате любые общие объекты, открытые DynaLoader, могут указывать на теперь недействительный «призрак» общего объекта libperl, вызывая, по-видимому, случайное повреждение памяти и сбои. Это поведение чаще всего наблюдается при использовании Apache и mod_perl, скомпилированных с механизмом APXS.
SunOS: dlclose($libref) HP-UX: ??? Linux: ??? VMS: ???(Функция dlclose() также используется Solaris и некоторыми версиями Linux и является распространённым выбором при предоставлении «обёртки» на других механизмах, как это делается в порте OS/2.)
- dl_load_flags()
-
Синтаксис:
$flags = dl_load_flags $modulename;Предназначен для вызова метода и переопределения производным классом (т. е. классом, у которого DynaLoader в его @ISA). Определение в самом DynaLoader возвращает 0, что приводит к стандартному поведению от dl_load_file().
- dl_find_symbol()
-
Синтаксис:
$symref = dl_find_symbol($libref, $symbol)Возвращает адрес символа $symbol или
undefесли не найден. Если целевая система имеет отдельные функции для поиска символов разных типов, то dl_find_symbol() должен сначала искать символы функций, а затем другие типы.Точный способ, которым адрес возвращается в $symref, в настоящее время не определён. Единственное первоначальное требование заключается в том, что $symref можно передавать и понимать dl_install_xsub().
SunOS: dlsym($libref, $symbol) HP-UX: shl_findsym($libref, $symbol) Linux: dld_get_func($symbol) and/or dld_get_symbol($symbol) VMS: lib$find_image_symbol($libref,$symbol) - dl_find_symbol_anywhere()
-
Синтаксис:
$symref = dl_find_symbol_anywhere($symbol)Применяет dl_find_symbol() к членам @dl_librefs и возвращает первую найденную пару.
- dl_undef_symbols()
-
Пример
@symbols = dl_undef_symbols()Возвращает список имён символов, которые остаются неопределёнными после load_file(). Возвращает
()если неизвестно. Не беспокойтесь, если ваша платформа не предоставляет механизма для этого. Большинство платформ не нуждаются в этом и, следовательно, не предоставляют его, они просто возвращают пустой список. - dl_install_xsub()
-
Синтаксис:
dl_install_xsub($perl_name, $symref [, $filename])Создаёт новую внешнюю подпрограмму Perl с именем $perl_name, используя $symref в качестве указателя на функцию, реализующую подпрограмму. Это просто прямой вызов newXS()/newXS_flags(). Возвращает ссылку на установленную функцию.
Параметр $filename используется Perl для идентификации исходного файла функции, если это необходимо для die(), caller() или отладчика. Если $filename не определён, то будет использоваться «DynaLoader».
- bootstrap()
-
Синтаксис:
bootstrap($module [...])
Это обычная точка входа для автоматической динамической загрузки в Perl.
Он выполняет следующие действия:
-
находит каталог auto/$module, выполняя поиск в @INC
-
использует dl_findfile() для определения имени файла для загрузки
-
устанавливает @dl_require_symbols в
("boot_$module") -
выполняет файл auto/$module/$module.bs, если он существует (обычно используется для добавления в @dl_resolve_using любых файлов, необходимых для загрузки модуля на текущей платформе)
-
вызывает dl_load_flags() для определения способа загрузки файла.
-
вызывает dl_load_file() для загрузки файла
-
вызывает dl_undef_symbols() и выводит предупреждение, если какие-либо символы не определены
-
вызывает dl_find_symbol() для "boot_$module"
-
вызывает dl_install_xsub() для его установки как "${module}::bootstrap"
-
вызывает &{"${module}::bootstrap"} для загрузки модуля (фактически используется ссылка на функцию, возвращаемая dl_install_xsub, для повышения скорости)
Все аргументы bootstrap() передаются в функцию загрузки модуля. По умолчанию сгенерированный код xsubpp ожидает $module [, $version]. Если необязательный аргумент $version не указан, он по умолчанию имеет значение
$XS_VERSION // $VERSIONв таблице символов модуля. По умолчанию код сравнивает версию пространства Perl с версией скомпилированного кода XS и выдает ошибку, если они не совпадают. -
АВТОР
Тим Бэнс, 11 августа 1994 года.
Этот интерфейс основан на работе и комментариях (в произвольном порядке): Ларри Уолла, Роберта Сандерса, Дина Роэриха, Джеффа Окамото, Анно Сигеля, Томаса Неймана, Пола Маркесса, Чарльза Бейли, меня и других.
Ларри Уолл разработал элегантный механизм наследования загрузки и реализовал первый динамический загрузчик Perl 5, используя его.
Глобальная загрузка Solaris добавлена Ником Ингом-Симмонсом с помощью помощи по разработке/кодированию от Тима Бэнса, январь 1996 года.
© 1993–2021 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.34.0/DynaLoader