Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

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

01.01.2007

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

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 чтобы получить адрес функции по имени.