Delphi - база знаний

       

Простой пример


Простой пример



Итак, попробуем рассказать в простоте. Вот есть у вас класс - примитивный калькулятор:

MyCalc=class
fx,fy:integer;  
public:
procedure SetOperands(x,y:integer)  
function Sum:integer;  


function Diff:integer;  
end;

procedure MyCalc.SetOperands(x,y:integer)
begin
fx:=x; fy:=y;  
end;

function MyCalc.Sum:integer;
begin
result:=fx+fy;  
end;

function MyCalc.Diff:integer;
begin
result:=fx-fy;  
end;

Все элементарно. Теперь если у вас есть объект этого класса, то вам не составит труда им воспользоваться.
Но представим следующую ситуацию: у вас есть один модуль, где объявлется объект этого класса. Допустим:

unit MyCalc

type
MyCalc=class
<описание выше>

var
Calc:MyCalc;


и теперь вы хотите использовать в другом модуле. Хорошо, скажите Вы, мы его просто подключим, и используем. Но, допустим, вы хотите, чтобы и другие могли пользоваться вашим объектом, даже используея другой компилятор. То есть нужно сделать так, чтобы ваш модуль можно было бы использовать без перекомпиляции. Как это сделать?

Ясно, что без каких-то стандартов не обойтись. Скорее всего, самый простой вариант выглядел бы так:

unit MyCalc

type
MyCalc=class  
<описание выше>

var Calc:MyCalc;

procedure SetOperands(x,y:integer)
begin
Calc.SetOperands(x,y);   
end;

function Sum:integer;
begin
result:= Calc.Sum;   
end;

function Diff:integer;
begin
result:= Calс.Diff;  
end;

procedure CreateObject;
begin
Calc:=MyCalc.Create;  
end;

procedure ReleaseObject;
begin
Calc.Free;  
end;

откомпилировать этот юнит, посмотреть, по какому адресу находятся функции SetOperands, Sum, Diff, CreateObject и ReleaseObject и приложить документацию где эти адреса будут указанны. Теперь каждый сможет загрузить ваш модуль в память и по адресу указанном в вашей документации вызвать нужную функцию.

Понятно, чем такой подход чреват. Это крайне не удобно. Но, эта проблема была поставленна давно, и теперь у нас есть стандартизированное соглашение об экспорте функций. То есть вместо того, чтобы писать для каждого модуля документацию с адресами функций при компиляции в заголовке модуля создается специальная стандартная таблица где указанны имена этих функций и их адреса (также указывается числовой индефикатор, который может быть использован вместо имени). Теперь уже лучше. Для того чтобы вызвать ваши функции, достаточно загрузить ваш модуль в память прочитать таблицу экспорта, и можно по именам в ней нати адреса функций и их вызвать. Так устроены DLL. Сейчас все это поддерживается компиляторами, и Windows API. То есть вам самому ничего этого делать не надо, а достаточно вызвать LoadLibrary, чтобы загрузить ваш модуль в память, и GetProcAddress чтобы получить адрес функции по имени.





Содержание раздела