2.4.1. Вызов внешних dll из паскаль скрипта¶
2.4.1.1. Общая информация¶
Возможность вызова методов из подгружаемых dll появилась с версии клиента 1.4.25.94.
Если библиотека еще не была загружена в приложение, то загрзуку библиотеки может выполнить явно и не явно.
2.4.1.2. Неявная загрузка Dll¶
Неявно вызов происходит перед вызовом метода описаного в паскаль скрипте с использованием специальной сигнатуры.
function MethodName(Arguments): ResultType; [CallingConvention;] external 'LibraryName' [MethodNameInExternalLibrary];
- Где:
- MethodName — имя метода;
- Arguments — аргументы;
- ResultType — возвращаемый тип;
- CallingConvention — соглашение вызова;
- LibraryName — имя библиотеки;
- MethodNameInExternalLibrary — имя метода во внешней библиотеке.
function MyFunction(arg: integer): integer; external 'MyCustomLib.dll'
В качестве соглашений вызова могут использоваться stdcall, register, pascal, cdecl, safecall. Более подробно: соглашение о вызове.
- В описании функции поддерживаются следующие типы:
- Integer
- Boolean
- Char
- Extended
- String
- Pointer
- PChar
- Object
- Class
- WideChar
- PWideChar
- AnsiString
- Currency
- Variant
- Interface
- WideString
- Int64
- Longint
- Cardinal
- Longword
- Single
- Byte
- Shortint
- Word
- Smallint
- Double
- Real
- DateTime
- Comp
- TObject - наследники (класс должен быть зарегистрирован в скриптере)
<pascal>
{ declaration of external functions }
function MessageBox(hwnd: pointer; text, caption: AnsiString; msgtype: integer): integer;
stdcall; external 'User32.dll' name 'MessageBoxA';
function GetDiskFreeSpace(root: AnsiString; var secPerCluster, bytesPerCluster, freeClusters,
totalClusters: integer): boolean; stdcall; external 'Kernel32.dll' name 'GetDiskFreeSpaceA';
function FindWindow(className, windowName: AnsiString): integer;
stdcall; external 'User32.dll' name 'FindWindowA';
function GetKeyState(virtKey: integer): short; stdcall; external 'User32.dll';
function FreeSpaceInfo(drive: String): string;
var a, b, c, d: word;
begin
if GetDiskFreeSpace(drive, a, b, c, d) then
result := Format('%d sections per cluster; %d bytes per cluster; %d free clusters; %d total clusters', [a, b, c, d])
else
result := '(could not get drive information)';
end;
const { windows consts }
MB_ICONQUESTION = $20;
MB_YESNO = $4;
IDYES = 6;
VK_SHIFT = $10;
begin
OutTxt := '';
if MessageBox(nil, 'Are you sure?', 'Confirmation', MB_ICONQUESTION + MB_YESNO) = IDYES then
OutTxt := OutTxt + 'MessageBox: user answered YES' + #13#10
else
OutTxt := OutTxt + 'MessageBox: user answered NO' + #13#10 ;
OutTxt := OutTxt + 'Drive C: free space: ' + FreeSpaceInfo('C:') + #13#10 ;
if FindWindow('TAppBuilder', '') > 0 then
OutTxt := OutTxt + 'Delphi is open' + #13#10
else
OutTxt := OutTxt + 'Delphi is not open' + #13#10 ;
if GetKeyState(VK_SHIFT) < 0 then
OutTxt := OutTxt + 'Shift is pressed' + #13#10
else
OutTxt := OutTxt + 'Shift is not pressed' + #13#10 ;
ShowMessage(OutTxt);
end;
</pascal>
2.4.1.3. Явная загрузка Dll¶
Явно загрузка выполняется с использованием метода LoadLibrary. Использование явной загрузки позволяет вручную управлять загрузкой и выгрузкой dll, тем самым писать более оптимизированный код. Использовать метод LoadLibrary следует в паре с методом FreeLibrary(dll) и конструкцией try finally.
<pascal>
{ declaration of external functions }
function CreateCustomForm(caption: AnsiString; color: integer): TObject; stdcall; external 'CustomLib.dll';
procedure ShowForm(form: TObject); external 'CustomLib.dll';
procedure GetBounds(form: TObject; var l, t, w, h: integer); cdecl; external 'CustomLib.dll' name 'FormGetBounds';
function DecodeToday(var year, month, day: integer): boolean; stdcall; external 'CustomLib.dll';
function tsr(x, y: double): double; external 'CustomLib.dll' name 'TimesSquareRoot';
const
clRed = $0000FF;
begin
{ explicit dynamic load of the library }
dll := LoadLibrary('CustomLib');
try
ShowMessage(Format('CustomLib.dll loaded: handle = %d', [dll]));
frm := CreateCustomForm('My form', clRed);
try
ShowForm(frm);
l := 0; t := 0;
w := 0; h := 0;
GetBounds(frm, l, t, w, h);
ShowMessage(Format('Form bounds: left=%d, top=%d, width=%d, height=%d', [l, t, w, h]));
finally
frm.Free;
end;
finally
FreeLibrary(dll); { unload }
ShowMessage(Format('DLL %d unloaded', [dll]));
end;
{ automatic load of the library on demand }
y := 0; m := 0; d := 0;
leap := DecodeToday(y, m, d);
ShowMessage(Format('Today: day=%d, month=%d, year=%d', [d, m, y]));
if leap then
ShowMessage(Format('%d is leap', [y]))
else
ShowMessage(Format('%d is not leap', [y]));
ShowMessage('Square root of ' + IntToStr(m * d) + ' is ' + FloatToStr(tsr(m, d)));
end;
</pascal>