На этом шаге мы рассмотрим особености использования объектов в DLL.
Если в DLL необходимо передать указатель на объект, созданный в основном приложении, или наоборот, использовать в вызывающем приложении созданный в DLL объект, возникает проблема несовместимости объектов. Типичный пример кода, иллюстрирующий эту проблему, приведен ниже:
procedure WhatObject(OB: Integer); var O: TObject; begin O := TObject(OB); if O is TButton then ShowMessage('Кнопка') else ShowMessage('Непонятно, что это такое'); end; procedure TForm1.Button1Click(Sender: TObject); begin WhatObject(Integer(Sender)); end;
Если оба этих метода реализованы в вызывающем приложении, то при щелчке на кнопке в форме появится сообщение "Кнопка". Если же метод WhatObject реализовать в DLL, то какой бы объект ни был указан в качестве параметра, всегда будет появляться сообщение "Непонятно, что это такое". Таким образом, можно сделать абсолютно корректный вывод о том, что нельзя создать объект в одном модуле, а использовать его в другом.
Почему работа с объектами в DLL реализована именно таким образом? Дело в том, что приложение и DLL могут быть реализованы на разных языках программирования. Соответственно, даже при одинаковых названиях классов число переменных в классе и/или их размер и/или порядок их следования могут различаться. То же самое относится и к методам класса. Поэтому в этом случае оператор is всегда возвращает False, а оператор as генерирует исключение.
И тем не менее в DLL можно использовать объекты, созданные в вызывающем приложении, и наоборот. Для этого необходимо, чтобы и DLL, и главное приложение были реализованы на одном и том же языке программирования. Ниже приведен пример подобного кода:
procedure ChangeColor(FM: Integer); begin TForm(FM).Color := clGreen; end; procedure TForm1.Button1Click(Sender: TObject); begin ChangeColor(Integer(Self)); end;
Метод ChangeColor реализован в DLL, а метод Button1Click - в приложении. И DLL, и приложение созданы в Delphi. Вызов метода ChangeColor будет вполне корректно работать, если в качестве параметра указывать на объект типа TForm (или потомка TForm). Однако в DLL нельзя проверить тип объекта перед его приведением к типу TForm, поэтому, если использовать в качестве параметра другой объект, произойдет запись в непредсказуемое место в памяти, и хорошо, если сразу же будет сгенерировано исключение.
Технология СОМ предоставляет альтернативный способ решения данной проблемы, позволяя создавать объекты в одном модуле, а применять в другом. Для этой цели используются интерфейсы.
На следующем шаге мы рассмотрим модальные формы в DLL.