COM объекты. ЛБ 1_Com. Лабораторная работа 1 часть 1 взаимодействие с унаследованным программным кодом 1 реализация внутреннего сервера com в delphi 2
Скачать 0.79 Mb.
|
ТРПОТРПО 1 ЛАБОРАТОРНАЯ РАБОТА №1 часть 1. 1 ВЗАИМОДЕЙСТВИЕ С УНАСЛЕДОВАННЫМ ПРОГРАММНЫМ КОДОМ 1 1.1. РЕАЛИЗАЦИЯ ВНУТРЕННЕГО СЕРВЕРА COM В DELPHI 2 1.2. ЗАДАНИЯ К ЛАБОРАТОРНОЙ РАБОТЕ 12 ЛАБОРАТОРНАЯ РАБОТА №1 часть 2. 12 РАЗРАБОТКА и ИСПОЛЬЗОВАНИЕ ActiveX ФОРМ 12 2.1. ПРИМЕР СОЗДАНИЯ КОМПОНЕНТА ActiveX В СРЕДЕ DELPHI 12 2.2. ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ 17 2.3. ОПИСАНИЕ МЕТОДОВ ШИФРОВАНИЯ 18 Шифр перестановки «Скитала» 18 Шифрующие таблицы 18 Применение магических квадратов 20 ШИФРЫ ПРОСТОЙ ЗАМЕНЫ 20 Полибианский квадрат 20 Система шифрования Цезаря 21 Аффинная система подстановок Цезаря 21 Система Цезаря с ключевым словом 22 Шифрующие таблицы Трисемуса 23 Биграммный шифр Плейфейра 23 Система омофонов 24 ШИФРЫ СЛОЖНОЙ ЗАМЕНЫ 25 Шифр Гронсфельда 26 Система шифрования Вижинера 26 Шифр "двойной квадрат" Уитстона 27 Роторные машины 28 ШИФРОВАНИЕ МЕТОДОМ ГАММИРОВАНИЯ 31 ЛАБОРАТОРНАЯ РАБОТА №1 часть 1.ВЗАИМОДЕЙСТВИЕ С УНАСЛЕДОВАННЫМ ПРОГРАММНЫМ КОДОМОчень часто сборки .NET должны успешно взаимодействовать со сложными приложениями, где значительную часть кода составляют классические СОМ- серверы. Код модулей СОМ является двоичным и платформенно-зависимым (в отличие от полностью платформенно-независимого кода IL). СОМ-серверы работают с уникальным набором типов данных (BSTR, VARIANT и т. п.), содержание которых в разных языках программирования сильно различается. В каждом программном модуле СОМ должны быть реализованы достаточно сложные элементы (такие как фабрики классов, код IDL, записи в реестр). В СОМ-объектах необходимо отслеживать каждую ссылку на объект. Eсли ошибиться в ссылках на объект, то это может привести к утечке памяти. Следовательно, между типами .NET и СОМ так мало общего, что трудно представить, как такие разные типы могут успешно взаимодействовать друг с другом. Но в реальной работе возникает очень много ситуаций, когда необходимо обеспечить такое взаимодействие. Платформа .NET поддерживает следующие виды совместимости с унаследованным кодом: вызовы из типов .NET напрямую к модулям DLL, созданным на С (то есть обращения к Win32 API или пользовательским модулям DLL); взаимодействие .NET и СОМ; применение элементов управления ActiveX в Windows Forms; вызовы из типов СОМ к типам .NET; В данной лабораторной работе будут рассмотрены пункты 2 и 3. 1.1. РЕАЛИЗАЦИЯ ВНУТРЕННЕГО СЕРВЕРА COM В DELPHIДля создания в Delphi внутреннего сервера СОМ, реализуемого библиотекой DLL, выполните команду File New | Other и на странице ActiveX Депозитария выберите пиктограмму ActiveX Library. Будет создан новый проект, который сохраните под каким-то именем, например, PMyComServ. Взгляните на созданный Delphi код этого проекта: library PMyComServ; uses ComServ; exports DllGetClassObject, DllCanUnloadNow, DllRegisterServer, DllUnregisterServer; ($R *.RES) begin end. . Оператор uses подключает к проекту модуль ComServ, в котором описан класс TComServ, реализующий свойства сервера СОМ. Объект ComServ этого класса автоматически создается в проекте и позволяет через свои свойства получать информацию о сервере и его объектах. Как видно из приведенного выше кода, библиотека экспонирует четыре функции. Все они вызываются в нужные моменты автоматически. Добавление в сервер объекта. Пусть это будет объект, имеющий два интерфейса, первый из которых имеет две арифметические функции: сложение и вычитание двух действительных чисел, а второй — функции умножения и деления действительных чисел. Выполните опять команду File New | Other и на странице ActiveX Депозитария выберите пиктограмму COM Object. Откроется окно (рис.1). В окне Class Name вы должны указать имя класса создаваемого объекта. К этому имени будет автоматически добавлен префикс «Т». Так что имя «MyObject», которое вы видите на рисунке 1, приведет к созданию класса TMyObject. Рисунок 1 – Добавление объекта Выпадающий список Instancing позволяет выбрать способ создания объекта (см. таблицу 1). Таблица 1 Описание способов создания объектов
В данном примере выбор в списке Instancing не имеет значения, так как для внутреннего сервера, который мы создаем, этот параметр игнорируется. Выпадающий список Threading model определяет способы вызова клиентами интерфейса объекта СОМ в многопоточных приложениях (см. таблицу 2). Таблица 2 Способы вызова клиентами интерфейса объекта СОМ в многопоточных приложениях
В окне Implemented interfaces задается имя интерфейса вашего объекта СОМ по умолчанию. Вы можете согласиться с предложенным именем, которое является именем класса с префиксом «I», или написать новое имя. Созданный интерфейс будет наследником IUnknown и в дальнейшем вы сможете задать его реализацию, пользуясь описанным далее редактором библиотеки типов. Вместо реализации нового интерфейса вы можете выбрать один из зарегистрированных в вашей системе, пользуясь кнопкой List. При использовании зарегистрированного интерфейса обязательно надо пользоваться этой кнопкой, так как если вы просто напишете в окне имя существующего интерфейса, система не поймет, что это не новый, а существующий интерфейс. Окно Description дает возможность ввести текстовое описание объекта СОМ. Индикатор Include Type Library определяет автоматическую генерацию библиотеки типов. Индикатор Mark interface OleAutornation разрешает маршаллинг — вызов функции интерфейса удаленными объектами в другом процессе и на другой машине, чтобы не усложнять свою задачу, выключите этот индикатор. После того, как вы заполните всю информацию в окне и щелкнете на ОК перед вами откроется окно редактора библиотеки типов (рисунок 2), а в окне Редактора Кода вы сможете увидеть заготовку модуля объекта СОМ. Она будет иметь вид: unit UObject; {$WARN SYMBOL_PLATFORM OFF} interface uses Windows, ActiveX, Classes, ComObj, PMyComServ_TLB, StdVcl; type TMyObjec=class (TTypedComObject, IMyObject) protected // Здесь объявляютсяметодыинтерфейса end; implementation uses ComServ; initialization TTypedComObjectFactory.Create(ComServer, TMyObject, Class_MyObject, ciMultilnstance, tmApartment); end. Вы видите, что в раздел initialization включен конструктор фабрики класса. Класс фабрики класса создан Delphi автоматически. Вызвав Менеджер Проектов (команда View Project Manager) вы увидите, что помимо этого модуля сгенерировался и включился в проект файл РМуComServ_TLB.pas — модуль библиотеки типов. Разработка методов созданного объекта. В первый момент после создания объекта окно редактора библиотеки типов (рис. 2) откроется автоматически. В дальнейшем вы в любой момент можете вызвать это окно командой View | Type Library. Эта команда доступна только в том случае, если ваш проект содержит библиотеку типов. Рисунок 2 - Редактор библиотеки типов В левой панели окна редактора библиотеки типов вы видите дерево элементов вашего объекта СОМ. Правая многостраничная панель позволяет посмотреть и задать свойства вершины, выделенной в левой панели. А инструментальная панель верху окна содержит быстрые кнопки, позволяющие вводить в объект новые интерфейсы, методы, свойства и т.п. Начнем с добавления методов в интерфейс IMyObject. Выделите в левой панели вершину этого интерфейса и щелкните на быстрой кнопке New Method. В дереве левой панели появится вершина нового метода. Назовите этот метод Add — он будет складывать два числа. Выделите вершину метода и перейдите в правой панели на страницу Parameters, которая показана на рисунке 3. В выпадающем списке Return Type надо выбрать тип возвращаемого методом значения - в нашем примере float. Для з адания параметров метода нажмите кнопку Add. Рисунок 3 - Определение входных и выходных параметров В нижнем окне панели появится строка, соответствующая вводимому параметру. В столбце Name надо задать имя параметра («Numberl» на рисунке 3). В столбце Туре надо выбрать из выпадающего списка тип параметра. В столбце Modifier можно выбрать модификаторы параметра: входной, выходной, необязательный, со значением по умолчанию и т.п. В нашем примере можно оставить значение по умолчанию «[in]». Аналогичным образом надо задать второй параметр. Далее так же, как вы добавили метод Add, добавьте в интерфейс метод Sub — вычитание чисел. Теперь надо ввести в объект второй интерфейс. Щелкните на быстрой кнопке New Interface (крайняя левая). В левой панели появится новая вершина. Назовите новый интерфейс «IMyObject2». Укажите для нового интерфейса родительский интерфейс – IUnknown. Выделите эту вершину, перейдите на правой панели на страницу Flags и выключите на ней флаги Dual и OleAutomation, чтобы не усложнять нашу задачу. Введите в новом интерфейсе так же, как делали раньше, два метода Mult — перемножение чисел, и Div — деление. Вы описали второй интерфейс. Теперь надо ввести его в ваш объект. Выделите в левой панели вершину объекта MyObject и перейдите в правой панели на страницу Implements. Щелкните на ней правой кнопкой мыши и выберите в контекстном меню раздел InsertInterface. Перед вами откроется окно со списком интерфейсов, которые вы можете добавить в свой объект. Выберите из него созданный вами интерфейс IMyObject2. Интерфейс включится в ваш объект. Описание объекта закончено. Теперь надо написать реализацию введенных методов. Щелкните на быстрой кнопке Refresh Implementation — обновить реализацию. Перейдите в редактор кода и посмотрите модуль объекта. Вы увидите в объявлении класса ссылку на оба интерфейса, объявления введенных вами методов, а в разделе implementation найдете заготовки реализации этих методов. Напишите в них соответствующие операторы. В результате модуль объекта приобретет вид: unit Unit1; {$WARN SYMBOL_PLATFORM OFF} interface uses Windows, ActiveX, Classes, ComObj, PMyComServ_TLB, StdVcl; type TMyObject = class(TTypedComObject, IMyObject, IMyObject2) protected function Add(Number1, Number2: Single): Single; stdcall; function Div_(Number1, Number2: Single): Single; stdcall; function Mult(Number, Number2: Single): Single; stdcall; function Sub(Number1, Number2: Single): Single; stdcall; {Declare IMyObject methods here} end; implementation uses ComServ; function TMyObject.Add(Number1, Number2: Single): Single; begin Result:=Number1+Number2; end; function TMyObject.Div_(Number1, Number2: Single): Single; begin Result:=Number1/Number2; end; function TMyObject.Mult(Number, Number2: Single): Single; begin Result:=Number*Number2; end; function TMyObject.Sub(Number1, Number2: Single): Single; begin Result:=Number1-Number2; end; initialization TTypedComObjectFactory.Create(ComServer, TMyObject, Class_MyObject, ciMultiInstance, tmApartment); end. Обратите внимание, что Delphi автоматически изменила имя метода Div на Div_, так как мы случайно задали методу имя, совпадающее с именем соответствующей операции Object Pascal. Чтобы в кодах не возникала двусмысленность, Delphi добавила в конце имени метода символ подчеркивания. Теперь все сделано, объект в составе сервера СОМ создан. Выполните компиляцию проекта (Project|Compile All Project). Осталось зарегистрировать сервер в системе. Это можно сделать командой Run | Register ActiveX Server главного меню Delphi. Если вы в дальнейшем надумаете удалить его (вряд ли наш тестовый сервер представляет какую-то ценность), вы должны будете выполнить команду Run | Unregister ActiveX Server. Отметим еще, что для распространения вашего проекта между пользователямивам потребуется библиотека типов на языке IDL Трансляция ее осуществляется быстрой кнопкой Export To IDL — крайняя правая на рисунке 3. Осталось проверить работу нашего сервера. Создайте тестовое приложение, включающее два окна Edit, в которых пользователь может задавать числа, две кнопки, одна из которых выполняет методы первого, а другая — второго интерфейса, и две метки для отображения результатов (рисунок 4.). Рисунок 4 - Тестовый пример Код этого приложения может сеть вид: unit Unit3; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,PMyComServ_TLB; type TForm1 = class(TForm) Edit1: TEdit; Edit2: TEdit; Label1: TLabel; Label2: TLabel; Button1: TButton; Button2: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; Interface1:IMyObject; Interface2:IMyObject2; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin Interface1:=CoMyObject.Create; Interface1.QueryInterface(ImyObject2,Interface2); end; procedure TForm1.Button1Click(Sender: TObject); begin Label1.Caption:=FloatToStr(Interface1.Add(StrToFloat(Edit1.Text),StrToFloat(Edit2.Text))); Label2.Caption:=FloatToStr(Interface1.Sub(StrToFloat(Edit1.Text),StrToFloat(Edit2.Text))); end; procedure TForm1.Button2Click(Sender: TObject); begin Label1.Caption:=FloatToStr(Interface2.Mult(StrToFloat(Edit1.Text),StrToFloat(Edit2.Text))); Label2.Caption:=FloatToStr(Interface2.Div_(StrToFloat(Edit1.Text),StrToFloat(Edit2.Text))); end; end. Обратите внимание прежде всего на то, что в оператор uses включена ссылка на модуль созданной вами библиотеки типов PMyComServ_TLB.pas. Далее после объявления класса формы вводятся две переменные Interface1 и Interface2 соответственно типов IMyObject и IMyObject2, объявленных в вашем объекте СОМ. Процедура FormCreate является обработчиком события OnCreate формы. Первый оператор этого обработчика создает CoClass класса CoMyObject и возвращает указатель на интерфейс по умолчанию IMyObject в переменную Interfacel. Чтобы получить указатель на второй интерфейс, используется функция Querylnterface первого интерфейса, в которую передаются как параметры имя второго интерфейса IMyObject2 и переменная Interface2. В результате переменной Interfaсе2 присваивается указатель на интерфейс IMyObject2. Код примера очевиден: при щелчках на той или иной кнопке в метки Label1 и Label2 заносятся результаты выполнения соответствующих методов интерфейсов с параметрами, получаемыми из окон Editl и Edit2. Для взаимодействия .NET с COM выполните следующие действия: Создайте проект в C# , изображенный на рисунке 5. Рисунок 5 – Пример COM-клиента на C# Выполните раннее связывание с СOM-сервером при помощи диалогового окна Add Reference (см. рисунок 6). Рисунок 6- Вызов диалогового окна Add Reference В появившемся диалоговом окне выбираете нужный COM-сервер (рис. 7). Рисунок 7 – Обращение к COM-серверу средствами Visual Studio .NET Для упрощения доступа к COM-серверу добавьте строку: namespace com { using PMyComServ; // !!!!! public partial class Form1 : Form { public Form1() { InitializeComponent(); } Объявите глобальные переменные: MyObject m; IMyObject i; IMyObject2 j; Для события Click кнопки Button1 (Интерфейс1) напишите следующий программный код: private void button1_Click(object sender, EventArgs e) { // Создаем объект MyObject m = new MyObject(); // Явным образом получаем ссылку на интерфейс IMyObject i = m; float s1 = Convert.ToSingle(textBox1.Text); float s2 = Convert.ToSingle(textBox2.Text); // Вызываем методы интерфейса IMyObject label1.Text = Convert.ToString(i.Add(s1, s2)); label2.Text = Convert.ToString(i.Sub(s1,s2)); } Для события Click кнопки Button2 (Интерфейс2) напишите следующий программный код: private void button2_Click(object sender, EventArgs e) { // Создаем объект MyObject m = new MyObject(); // Явным образом получаем ссылку на интерфейс IMyObject i = m; // Получаем ссылку на интерфейс IMyObject2 // через интерфейс IMyObject j = (IMyObject2)i; float s1 = Convert.ToSingle(textBox1.Text); float s2 = Convert.ToSingle(textBox2.Text); label1.Text = Convert.ToString(j.Mult(s1, s2)); label2.Text = Convert.ToString(j.Div(s1, s2)); } |