Spec-Zone.ru › Tcl/Tk

Загрузка

Имя

load — Загрузка машинного кода и инициализация новых команд

Синтаксис

load ?-global? ?-lazy? ?--? имяФайла
load ?-global? ?-lazy? ?--? имяФайла имяПакета
load ?-global? ?-lazy? ?--? имяФайла имяПакета интерпретатор

Описание

Эта команда загружает двоичный код из файла в адресное пространство приложения и вызывает процедуру инициализации в пакете для его включения в интерпретатор. имяФайла — имя файла, содержащего код; его точный формат зависит от системы, но на большинстве систем это общая библиотека, например, файл .so под Solaris или DLL под Windows. имяПакета — имя пакета, используемое для вычисления имени процедуры инициализации. интерпретатор — имя пути интерпретатора, в который необходимо загрузить пакет (см. руководство по interp для получения подробностей); если интерпретатор опущен, он по умолчанию устанавливается в интерпретатор, в котором была вызвана команда load.

После загрузки файла в адресное пространство приложения будет вызвана одна из двух процедур инициализации в новом коде. Обычно процедура инициализации добавляет новые команды к интерпретатору Tcl. Имя процедуры инициализации определяется значением имяПакета и тем, является ли целевой интерпретатор безопасным. Для обычных интерпретаторов имя процедуры инициализации будет иметь вид pkg_Init, где pkg такое же, как имяПакета, за исключением того, что первая буква преобразуется в верхний регистр, а все остальные — в нижний. Например, если имяПакета равно foo или FOo, имя процедуры инициализации будет Foo_Init.

Если целевой интерпретатор является безопасным интерпретатором, то имя процедуры инициализации будет pkg_SafeInit вместо pkg_Init. Функция pkg_SafeInit должна быть написана тщательно, чтобы она инициализировала безопасный интерпретатор только с частичной функциональностью, предоставляемой пакетом, безопасной для использования ненадёжным кодом. Более подробную информацию о Safe-Tcl см. в справке по команде safe.

Процедура инициализации должна соответствовать следующему прототипу:

typedef int Tcl_PackageInitProc(
        Tcl_Interp *interp);

Аргумент интерпретатор идентифицирует интерпретатор, в который должен быть загружен пакет. Процедура инициализации должна возвращать TCL_OK или TCL_ERROR, чтобы указать, завершилась ли она успешно; в случае ошибки она должна установить результат интерпретатора на сообщение об ошибке. Результатом команды load будет результат, возвращённый процедурой инициализации.

Фактическая загрузка файла выполняется только один раз для каждого имяФайла в приложении. Если заданный имяФайла загружается в несколько интерпретаторов, то первый load загрузит код и вызовет процедуру инициализации; последующие load вызовут процедуру инициализации без повторной загрузки кода. Для версий Tcl ниже 8.5 невозможно выгрузить или перезагрузить пакет. Однако с версии 8.5 команда unload позволяет выгружать библиотеки, загруженные с помощью load, для библиотек, которые осведомлены о механизме выгрузки Tcl.

Команда load также поддерживает пакеты, статически связанные с приложением, если эти пакеты были зарегистрированы путём вызова процедуры Tcl_StaticPackage. Если имяФайла пустая строка, то имяПакета должно быть указано.

Если имяПакета опущено или указано как пустая строка, Tcl пытается угадать имя пакета. Это может быть сделано по-разному на разных платформах. По умолчанию, используемое на большинстве UNIX-платформ, — взять последний элемент имяФайла, удалить первые три символа, если они lib, и использовать любые следующие символы и подчеркивания в качестве имени модуля. Например, команда load libxyz4.2.so использует имя модуля xyz, а команда load bin/last.so {} использует имя модуля last.

Если имяФайла пустая строка, то имяПакета должно быть указано. Команда load сначала ищет статически загруженный пакет (который был зарегистрирован вызовом процедуры Tcl_StaticPackage) с таким именем; если такой найден, он используется. В противном случае команда load ищет динамически загруженный пакет с таким именем и использует его, если он найден. Если несколько различных файлов были загружены с помощью load с разными версиями пакета, Tcl выбирает файл, который был загружен первым.

Если указан -global перед именем файла, все символы, найденные в общей библиотеке, экспортируются для глобального использования другими библиотеками. Опция -lazy откладывает фактическую загрузку символов до их первого фактического использования. Опции могут быть сокращены. Опция -- указывает конец опций и должна использоваться, если вы хотите использовать имя файла, начинающееся с -, и вы предоставили имяПакета команде load.

На платформах, которые не поддерживают опции -global или -lazy, опции все равно существуют, но не имеют никакого эффекта. Обратите внимание, что использование опций -global или -lazy может привести к сбою вашего приложения позже (в случае конфликтов символов или отсутствия символов), которые нельзя обнаружить во время load. Поэтому используйте их только тогда, когда вы знаете, что делаете; вы не получите приятного сообщения об ошибке, когда что-то не так с загруженной библиотекой.

Проблемы с переносимостью

Windows
Когда загрузка завершается ошибкой «библиотека не найдена», возможно, также не была найдена зависимая библиотека. Чтобы увидеть зависимые библиотеки, введите «dumpbin -imports <dllname>» в консоли DOS, чтобы увидеть, что библиотека должна импортировать. При загрузке DLL в текущем каталоге Windows игнорирует «./» как спецификатор пути и использует эвристический поиск для нахождения DLL вместо этого. Чтобы избежать этого, загрузите DLL с помощью:
load [file join [pwd] mylib.DLL]

Ошибки

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

Пример

Следующее — минимальное расширение:
#include <tcl.h>
#include <stdio.h>
static int fooCmd(ClientData clientData,
        Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
    printf("called with %d arguments\n", objc);
    return TCL_OK;
}
int Foo_Init(Tcl_Interp *interp) {
    if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
	return TCL_ERROR;
    }
    printf("creating foo command");
    Tcl_CreateObjCommand(interp, "foo", fooCmd, NULL, NULL);
    return TCL_OK;
}

При построении в общей/динамической библиотеке с подходящим именем (например, foo.dll в Windows, libfoo.so в Solaris и Linux) его можно затем загрузить в Tcl следующим образом:

# Load the extension
switch $tcl_platform(platform) {
    windows {
        load [file join [pwd] foo.dll]
    }
    unix {
        load [file join [pwd] libfoo[info sharedlibextension]]
    }
}

# Now execute the command defined by the extension
foo

См. также

info sharedlibextension, package, Tcl_StaticPackage, safe

Licensed under Tcl/Tk terms
https://www.tcl.tk/man/tcl/TclCmd/load.htm

Licensed under Tcl/Tk terms
https://www.tcl.tk/man/tcl/TclCmd/load.htm

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API