Lib.CreateCallbackFunction

From SunFlurry wiki
Revision as of 13:58, 17 January 2024 by Admin (talk | contribs) (1 revision imported)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
  CreateCallbackFunction (Создание функции обратного вызова)
Объект:Библиотека
Статус разработки: Реализована
Тип:Функция
Обращение к БД:Нет
Исключения:Невозможно превратить в строку, локальная функция не найдена, неверные аргументы, системная ошибка.
Визуальность:Нет

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

Синтаксис

Lib.CreateCallbackFunction(<Имя функции (STRING)>,<Глубина поиска (INT)>=0,<Способ вызова (STRING)>="Stdcall",<Аргументы функции (STRING)>,<Возвращаемое значение (STRING)>):<Новый объект функции обратного вызова (CBFUNCTION)>

Аргументы

  • <Имя функции (STRING)> - Аргумент задает имя локальной или глобальной функции, которой будет передано управление в момент внешнего вызова системной функции, задаваемой своим адресом.
  • <Глубина поиска (INT)> - (необязательный аргумент) Задает способ поиска локальной функции. Может принимать следующие значения:
    • 0 (по умолчанию) -- выполнять поиск во всех модулях большего уровня вложенности (родительских) и во всех глобальных модулях.
    • 1 -- выполнять поиск только внутри текущего модуля.
    • 2 -- выполнять поиск только внутри родительского модуля.
    • 3..x -- выполнять поиск только внутри родительского модуля указанного уровня (к примеру, для уровня 3, выполнять поиск только в родителе родителя текущего модуля).
  • <Способ вызова (STRING)> - (необязательный аргумент) Аргумент задает способ вызова функции системной функции снешним источником (см. статью для дополнительной информации). Возможны следующие значения аргумента:
    • stdcall (x86,x64) -- стандартный способ вызова функций Windows, используется по умолчанию. Для x64 является единственным доступным способом вызова.
    • cdecl (x86) -- используется при вызове из среды, скомпилированной с помощью C или C++.
    • fastcall (x86) -- используется при вызове из среды, скомпилированной с помощью C или C++, когда вызываемая функция там помечена, как fastcall.
    • register (x86) -- используется при вызове из функций, скомпилированных с помощью Delphi или Free Pascal. Важно понимать, что, возможно, придется пометить некоторые параметры при вызове таких функций с помощью префикса "+" (см. ниже).
    • vectorcall (x86,x64) -- способ вызова, оперирующий длинными числами (128 бит), в данный момент не поддерживается.
  • <Аргументы функции (STRING)> - (необязательный аргумент) Задает список и тип аргументов, передаваемых функции. Строка имеет следующий формат: <Аргумент 1>,<Аргумент 2>,.... Где аргумент имеет следующий формат: [<Префиксы типа данных>]<Тип данных аргумента>[<Размер типа данных>]. Далее даются все возможные префиксы и наименования типов данных:
    • ^ (префикс) -- определяет то, что аргумент будет являться ссылкой (указателем, pointer) на данные, а не самими данными.
    • ^^ (префикс) -- определяет то, что аргумент будет являться ссылкой (указатель, pointer) на ссылку на данные, а не самими данными. Префикс можно эмулировать с помощью манипуляции с буфером данных.
    • @ (префикс) -- определяет то, что аргумент будет являться ссылкой (указателем, pointer) на данные, а не самими данными. Также помечает аргументы "by ref", т.е., аргументы, значение которых может быть изменено функцией и должно быть передано назад в вызывавшую программу. Важно: без этого префикса, измененные функцией значения не будут переданы назад, даже если аргумент локальной функции имеет префикс ByRef. Префикс может дополняться префиксом ^, если необходимо.
    • U (префикс) -- используется для типов I или N, указывает на то, что данные представляют собой беззнаковое число (по умолчанию число со знаком)
    • + (префикс) -- определяет то, что данный аргумент всегда будет передаваться в стек, а не с помощью регистра процессора. Флаг имеет значение только для способа вызова функции register. Для его использования необходимо полностью понимать, как работает вызов функции (calling convention) такого типа. Обычно нет необходимости в использовании этого префикса, система сама правильно определит какие аргументы будут передаваться в стек, а какие с помощью регистров.
    • I<Размер в битах> или Int<Размер в битах> (наименование типа данных) -- задает целый тип аргумента. Размер может принимать следующие значения: 8, 16, 32, 64.
    • N или Native (наименование типа данных) -- задает целый тип аргумента с размером, задаваемым текущей архитектурой исполнения приложения. Для x86 длина поля будет представлять 32 бита, для x64 -- 64 бита.
    • R<Размер в битах> или Real<Размер в битах> (наименование типа данных) -- задает вещественный тип аргумента. Размер может принимать следующие значения: 32 (одинарная точность), 64 (двойная точность), 80 (расширенная точность). Расширенная точность не поддерживается при стандартных вызовах "x64" функций, при написании расширения программы, можно пользоваться, к примеру, ссылкой на вещественное число (P) и получение его из буфера.
    • B<Размер в битах> или Bool<Размер в битах> (наименование типа данных) -- задает булевый тип аргумента. Размер может принимать следующие значения: 8, 16, 32, 64.
    • P или Pointer (наименование типа данных) -- задает тип данных указателя на данные. Для x86 длина поля будет поставлять 32 бита, для x64 -- 64 бита. При вызове функцией в аргументах такого типа удобно возвращать объекты буфера или записи.
    • SZ<Размер в байтах> или SZW<Размер в словах> (наименование типа данных) -- задает аргумент с типом строка, заканчивающаяся нулевым символом. Строка может иметь формат ANSI (SZ) или UTF-16 (SZW). Строки всегда должны быть объявлены с префиксом ^ (ссылка на данные). Размер может принимать нулевое значение, если заранее неизвестно, строка какого размера будет использоваться. В случае нулевого размера, однако, при подготовке аргумента, размер будет выделен точно под строку. Кроме строковых значений, система принимает также буферы или записи (для которых вызов выполняется несколько быстрее, чем для строк).
    • S<Размер в байтах> или SW<Размер в словах> (наименование типа данных) -- задает аргумент с типом строка фиксированной длины. Строка может иметь формат ANSI (S) или UTF-16 (SW). Строки всегда должны быть объявлены с префиксом ^ (ссылка на данные). Размер может принимать нулевое значение, если заранее неизвестно, строка какого размера будет использоваться. В случае нулевого размера, однако, при подготовке аргумента, размер будет выделен точно под строку. Кроме строковых значений, система принимает также буферы (для которых вызов выполняется несколько быстрее, чем для строк).
  • <Возвращаемое значение (STRING)> - (необязательный аргумент) Имеет формат одного аргумента функции (см. выше), если аргумент опущен, возвращаемое функцией значение будет игнорировано (функция не возвращает значения).

Возвращаемое значение

Возвращается новый объект функции обратного вызова.

Примеры

//Пример производит вывод на экран заголовков и наименований классов всех видимых верхних окон системы.
Var aUser32 Export;

  Function EnumWindowsProc(hwnd,LParam)
    If aUser32.IsWindowVisible(hwnd) Then
      СтрИмя:="";
      aUser32.GetWindowText(hwnd,СтрИмя,4095);
      СтрКласс:="";
      aUser32.GetClassName(hwnd,СтрКласс,4095);
      Message(""+hwnd+":"+СтрКласс+?(СтрИмя<>"","("+СтрИмя+")"));
    EndIf;
    Result:=1;
  EndFunction

//Загрузка нужных системных функций
aUser32:=Lib.Load("user32.dll");
aUser32.RegisterFunction("EnumWindows","stdcall","P,N","B32");
aUser32.RegisterFunction("GetWindowTextW:GetWindowText","stdcall","N,@SZW4096,I32","I32");
aUser32.RegisterFunction("GetClassNameW:GetClassName","stdcall","N,@SZW4096,I32","I32");
aUser32.RegisterFunction("IsWindowVisible","stdcall","N","B32");

//Создание функции объекта для вызова EnumWindowsProc из системной области памяти
aEnumWindowsProc:=Lib.CreateCallbackFunction("EnumWindowsProc",,"stdcall","I32,N","B32");

//Вызов системной функции EnumWindowsProc, которая, в свою очередь, будет вызывать созданную ранее EnumWindowsProc для каждого найденного окна
aUser32.EnumWindows(aEnumWindowsProc,0);