Второй способ вызова называется динамическим связыванием и отличается, прежде всего тем, что библиотека помещается в память только на время выполнения, а потом выгружается. Рассмотрим следующий код:
procedure TForm1.Button1Click(Sender: TObject);
TYPE
TFunc = Function (a,b,c:real):REAL; STDCALL;
CONST DLLName='geta.DLL'; // имя DLL
VAR a,b,c:REAL;
Handle:THandle;
F:TFunc;
begin
Label1.Caption:='';
TRY
a:=StrToFloat(LabeledEdit1.Text);
b:=StrToFloat(LabeledEdit2.Text);
c:=StrToFloat(LabeledEdit3.Text)
EXCEPT
Label1.Caption:='Ошибка ввода!';
Exit
END;
Handle := LoadLibrary(DLLName); // загрузка библиотеки
IF ( Handle <> 0 ) THEN
BEGIN
// получение адреса функции GetArea в библиотеке
@F:=GetProcAddress(Handle,'GetArea');
IF Assigned(F) THEN
BEGIN
// вызов функции
Label1.Caption:='S='+FloatToStrF(F(a,b,c),ffFixed,10,4);
// выгрузка библиотеки из памяти
FreeLibrary(Handle)
END
END
ELSE
MessageDlg('Не найдена библиотека '+DLLName,mtWarning,[mbOK],0)
end;
Для динамического вызова, прежде всего, надо загрузить библиотеку при помощи функции LoadLibrary(имя_библиотеки). Эта функция возвращает ссылку на библиотеку, которую мы записываем в переменную типа Thandle. Теперь надо получить адрес функции GetArea, спрятанной в библиотеке. Его возвращает функция GetProcAddress(ссылка_на_библиотеку,имя_функции). А далее начинаются трюки. Для вызова функции из библиотеки надо описать особый тип данных – ссылку на функцию. В нем указывается, какие аргументы подаются на вход функции и значение какого типа она возвращает. Тип TFunc = Function (a,b,c:real):REAL; STDCALL; соответствует функции с любым именем, на вход которой надо подать три вещественных числа и которая возвращает одно вещественное число, используя стандартную модель вызова. Объявим переменную F типа TFunc. В нее и запишем адрес функции GetArea. Для этого используется символ @, означающий получение адреса переменной. Таким образом, в строке
@F:=GetProcAddress(Handle,'GetArea');
происходит следующее: переменная F размещается в памяти по тому же адресу, по которому в памяти расположен код функции GetArea. После этого переменная F превращается в ссылку на функцию, поэтому вполне законна запись F(a,b,c), означающая вызов функции GetArea с аргументами a,b,c. Наконец, команда FreeLibrary(ссылка_на_библиотеку) выгружает DLL из памяти.
В приведенном фрагменте предусмотрен ряд "затычек". Проверка условия Handle<>0 позволяет установить, удалось ли загрузить библиотеку (вдруг ее просто нет?) Условие Assigned(F) проверяет, удалось ли получить адрес функции в библиотеке.
Динамическое связывание позволяет подключаться к чужим DLL – достаточно знать, какие процедуры и функции в них находятся и с какими параметрами их надо вызывать.