Диспетчерские интерфейсы и Автоматизация. Коммуникация между клиентом и компонентом IID_IX IID_IY IUnknown IX IY.

Презентация:



Advertisements
Похожие презентации
Фабрики Класса IDL. Создание компонента - 1 // // Функция создания // extern C IUnknown* CreateInstance() { IUnknown* pI = (IUnknown*)(void*)new CA; PI->AddRef();
Advertisements

Компоненты: Повторное применение; Использование..
COM в Visual FoxPro 6.0 (основные понятия) COM в Visual FoxPro ® 6.0 (основные понятия) Дроздов Михаил Компания «ИВС Софт» My Page: My Page:
WinCC Работа и мониторинг Siemens AG All rights reserved.© TC Nbg.-M Date: File: E04ODKe.PPT Catalog: EWINCC ODK - WinCC - API.
Функции с переменным числом аргументов private static int Sum(int a, int b) { return a + b; } static void Main() { int sum = Sum(1, 2); } 1 Функции.
1. Понятие распределенной системы 2. Архитектура предприятия 3. Декомпозиция распределенных систем 4. Сетевой клиент 5. Сетевой сервер Вопросы.
COM- технология COM- сервер :48:021.
Загруженная в оперативную память программа (ЕХЕ-файл) становится процессом. Процесс - это выполняемая программа, процесс имеет свою память, описатели.
1 A + B Операнд 1Операнд 2 Оператор Что такое выражение (expression) ? Что такое инструкция (statement) ? Операторы int max = (a > b) ? a : b;
Синтаксис языка Java. Символы и синтаксис Перевод строчки эквивалентен пробелу Регистр в именах различается.
Лекция 22. Шаблоны (часть 2) Красс Александр СПбГУ ИТМО, 2008.
Class Date { private int year = 0; private int month = 0; private int day = 0; public void SetDate (int y, int m, int d) { year = y; month = m; day = d;
Лекция 9 Приведение типов. Классификация типов Типы С++ Пользовательские Встроенные (Фундаментальные) Адресные Арифтметические void Указатели Ссылки Массивы.
Инструкции C++ Условная инструкция Формат: if (условие) оператор; else оператор; Пример: if (i!=0) { if (j) j++; if(k) k++; else if(p) k--; } else i--;
Функции Функция – именованная последовательность описаний и операторов, выполняющая некоторое действие. Может иметь параметры и возвращать значение. Функция.
Лекция 4. Введение в С++ Наследование, множественное наследование. Конструкторы, деструкторы. Виртуальные функции.
Статические поля класса Статические поля хранят данные, общие для всех элементов класса. Статическое поле существует в единственном экземпляре для всех.
Лекция 6 Функции. Объявления и определения Объявление функции – указание имени функции, а также входных и выходных параметров Определение функции – указание.
Test 16 Вопрос 1. class Clazz { { System.out.println("non-static init"); } public static void main(String a[]) { System.out.println("main"); Clazz ob1.
Преобразования типов В языке C/C++ имеется несколько операций преобразования типов. Они используются в случае, если переменная одного типа должна рассматриваться.
Транксрипт:

Диспетчерские интерфейсы и Автоматизация

Коммуникация между клиентом и компонентом IID_IX IID_IY IUnknown IX IY

Automation IUnknown IDispatch ICustom

«Кухня» обращения через указатель на интерфейс или & FxStringOut & FxArrayIn & FxLoadMotor & FxArrayIn & FxLoadMotor & FxStringOut N N

Индекс указателя на функцию pIX->FxStringOut(msg); Это на самом деле: (*(pIX->pvtbl[IndexOfFxStringOut]))(pIX, msg);

А что знает клиент? ProgID Имя функции Аргументы

IDispatch interface IDispatch : IUnknown { HRESULT GetTypeInfoCount([out] UINT * pctinfo); HRESULT GetTypeInfo([in] UINT iTInfo, [in] LCID lcid, [out] ItypeInfo ** ppTInfo); HRESULT GetIDsOfNames([in] REFIID riid, [in, size_is(cNames)] LPOLESTR * rgszNames, [in] UINT cNames, [in] LCID lcid, [out, size_is(cNames)] DISPID * rgDispId); HRESULT Invoke([in] DISPID dispIdMember, [in] REFIID riid, [in] LCID lcid, [in] WORD wFlags, [in, out] DISPPARAMS * pDispParams, [out] VARIANT * pVarResult, [out] EXCEPINFO * pExcepInfo, [out] UINT * puArgErr); };

Традиционный и disp-интерфейс

Реализация Invoke с помощью СОМ

Дуальный интерфейс

Использование IDispatch в VB Dim Cmpnt As Object Set Cmpnt = CreateObject(InsideCOM.Chap11.Cmpnt11) Cmpnt.Fx

Использование IDispatch в С // Инициализировать библиотеку OLE. HRESULT hr = OleInitialize(NULL); // Получить CLSID приложения. wchar_t progid[] = LInsideCOM.Chap11; CLSID clsid; hr = ::CLSIDFromProgID(progid, &clsid); // Создать компонент. IDispatch* pIDispatch = NULL; hr = ::CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (void**)&pIDispatch); DISPID dispid; OLECHAR* name = LFx; pIDispatch->GetIDsOfNames( IID_NULL, // Должно быть IID_NULL &name, // Имя функции 1, // Число имен GetUserDefaultLCID(), // Информация локализации &dispid); // Диспетчерский идентификатор

Использование IDispatch в С // Подготовить аргументы для Fx DISPPARAMS dispparamsNoArgs = { NULL, 0, // Ноль аргументов 0, // Ноль именованных аргументов }; // Простейший вызов Invoke pIDispatch->Invoke(dispid, // DISPID IID_NULL, // Должно быть IID_NULL GetUserDefultLCID(), // Информация локализации DISPATCH_METHOD, // Метод &dispparamsNoArgs, // Аргументы метода NULL, // Результаты NULL, // Исключение NULL); // Ошибка в аргументе

Параметры Invoke HRESULT Invoke( [in] DISPID dispIdMember, [in] REFIID riid, [in] LCID lcid, [in] WORD wFlags, [in, out] DISPPARAMS * pDispParams, [out] VARIANT * pVarResult, [out] EXCEPINFO * pExcepInfo, [out] UINT * puArgErr );

Параметры Invoke: методы и свойства Функция: HRESULT hr = pIX->Fx(...); Свойство: pIX->State = true; int count = pIX->Counts;

Параметры Invoke: методы и свойства if (pIWindow->GetVisible() == FALSE) { pIWindow->SetVsible(TRUE); } Код VB If Window.Visible = False Then Window.Visible = True End If

Параметры Invoke: методы и свойства [ object, uuid(D15B6E D0-A6BB-0080C7B2D682), pointer_default(unique), dual ] interface IWindow : IDispatch {... [propput] HRESULT Visible([in] VARIANT_BOOL bVisible); [propget] HRESULT Visible([out, retval] VARIANT_BOOL* pbVisible);... }

Параметры Invoke: методы и свойства get_Visible() - PROPGET – получение свойства set_Visible(TRUE) - PROPPUT – задание свойства

Параметры Invoke: методы и свойства Visible DISPATCH_METHOD - метод DISPATCH_PROPERTGET – получение свойства DISPATCH_PROPERTYPUT – задание свойства DISPATCH_PROPERTYPUTREF – задание по ссылке

Параметры Invoke: параметры disp- интерфейсов typedef struct tagDISPPARAMS { // Массив аргументов VARIANTARG* rgvarg; // DISPID для именованных аргументов DISPID* rgdispidNamedArgs; // Число аргументов unsigned int cArgs; // Число именованных аргументов unsigned int cNamedArgs; } DISPPARAMS;

Параметры Invoke: возврат результатов pVarResult это указатель на VARIANT результата выполнения Invoke

Параметры Invoke: исключения typedef struct tagEXCEPINFO { WORD wCode; // Код ошибки WORD wReserved; BSTR bstrSource; // Источник исключительной ситуации BSTR bstrDescription; // Описание ошибки BSTR bstrHelpFile; // Полное имя файла справки DWORD dwHelpContext; // Контекст внутри файла справки ULONG pvReserved; ULONG pfnDefferedFillIn; // Функция для заполнения этой структуры SCODE scode; // Код возврата } EXCEPINFO;

Параметры Invoke: исключения EXCEPINFO excepinfo; HRESULT hr = pIDispatch->Invoke(..., &excepinfo); if (FAILED(hr)) { // Ошибка при вызове Invoke if (hr == DISP_E_EXCEPTION) { // Метод сгенерировал исключение. // Сервер может отложить заполнение EXCEPINFO. if (excepinfo.pfnDefferedFillIn != NULL) { // Заполнить структуру EXCEPTINFO (*(excepinfo.pfnDefferedFillIn)(&excepinfo); } strstream sout; sout

Параметры Invoke: ошибки в аргументах Если возвращаемое значение DISP_E_PARAMNOTFOUND, либо DISP_E_TYPEMISMATCH, то в puArgErr – индекс аргумента, вызвавшего ошибку.

Тип VARIANT typedef struct tagVARIANT { VARTYPE vt; unsigned short wReserved1; unsigned short wReserved2; unsigned short wReserved3; union { Byte bVal; // VT_UI1. Short iVal; // VT_I2. long lVal; // VT_I4. float fltVal; // VT_R4. double dblVal; // VT_R8. VARIANT_BOOL boolVal; // VT_BOOL. SCODE scode; // VT_ERROR. CY cyVal; // VT_CY. DATE date; // VT_DATE. BSTR bstrVal; // VT_BSTR. // см.далее

Тип VARIANT DECIMAL FAR* pdecVal // VT_BYREF|VT_DECIMAL. IUnknown FAR* punkVal; // VT_UNKNOWN. IDispatch FAR* pdispVal; // VT_DISPATCH. SAFEARRAY FAR* parray; // VT_ARRAY|*. Byte FAR* pbVal; // VT_BYREF|VT_UI1. short FAR* piVal; // VT_BYREF|VT_I2. long FAR* plVal; // VT_BYREF|VT_I4. float FAR* pfltVal; // VT_BYREF|VT_R4. double FAR* pdblVal; // VT_BYREF|VT_R8. VARIANT_BOOL FAR* pboolVal; // VT_BYREF|VT_BOOL. SCODE FAR* pscode; // VT_BYREF|VT_ERROR. CY FAR* pcyVal; // VT_BYREF|VT_CY. DATE FAR* pdate; // VT_BYREF|VT_DATE. BSTR FAR* pbstrVal; // VT_BYREF|VT_BSTR. // см.далее

Тип VARIANT IUnknown FAR* FAR* ppunkVal; // VT_BYREF|VT_UNKNOWN. IDispatch FAR* FAR* ppdispVal; // VT_BYREF|VT_DISPATCH. SAFEARRAY FAR* FAR* pparray; // VT_ARRAY|*. VARIANT FAR* pvarVal; // VT_BYREF|VT_VARIANT. void FAR* byref; // Generic ByRef. char cVal; // VT_I1. unsigned short uiVal; // VT_UI2. unsigned long ulVal; // VT_UI4. int intVal; // VT_INT. unsigned int uintVal; // VT_UINT. char FAR * pcVal; // VT_BYREF|VT_I1. unsigned short FAR * puiVal; // VT_BYREF|VT_UI2. unsigned long FAR * pulVal; // VT_BYREF|VT_UI4. int FAR * pintVal; // VT_BYREF|VT_INT. unsigned int FAR * puintVal; //VT_BYREF|VT_UINT. };

Тип VARIANT - определение // Выделить и инициализировать аргумент VARIANT VARIANTARG varg; ::VariantInit(&varg); // Инициализировать VARIANT. varg.vt = VT_R8; // Тип данных VARIANT - double varg.dblVal = 5.678; // Данные для VARIANT // Выделить и инициализировать аргумент VARIANT VARIANTARG varg2; ::VariantInit(&varg2); // Инициализировать VARIANT. varg2.vt = VT_BSTR; // Тип данных VARIANT - double varg2.bstrVal = bstrIn; // Данные для VARIANT

Тип VARIANT – преобразование подтипов HRESULT VariantChangeType( VARIANTARG* pVarDest, // Преобразованное значение VARIANTARG* pVarSrc, // Исходное значение unsigned short wFlags, VARTYPE vtNew // Целевой тип преобразования }

Тип VARIANT – преобразование подтипов BOOL VariantToDouble(VARIANTARG* pvarSrc, double* pd) { VARIANTARG varDest; VariantInit(&varDest); HRESULT hr = VariantChangeType(&varDest,pvarSrc, 0, VT_R8); if (FAILED(hr)) { return FALSE; } *pd = varDest.dblVal; return TRUE; }

Тип VARIANT – функции поддержки VariantInit VariantChangeType VariantClear VariantCopy VariantCopyInd

Тип BSTR

BSTR bstr = LГде же счетчик?; // Неправильно wchar_t wsz[] = LВот где счетчик; BSTR bstr; bstr = SysAllocString(wsz); … SysFreeString(wsz);

Тип BSTR – функции поддержки SysAllocString – создание и инициализация строки SysFreeString – освобождение строки SysAllocStringByteLen – строка указанной длины с нулём на конце SysAllocStringLen – строка указанной длины SysReAllocString – изменение содержимого и длины SysReAllocStringLen – изменение длины SysStringByteLen – длина строки в байтах SysStringLen – длина строки

Тип данных SAFEARRAY typedef struct tagSAFEARRAY { unsigned short cDims; // Число измерений unsigned short fFeatures; unsigned long cbElements; // Размер каждого элемента unsigned long clocks; // Счетчик блокировок BYTE* pvData; // Указатель на данные [size_is(cDims)] SAFEARRAYBOUND rgsabound[]; } SAFEARRAY; typedef struct tagSAFEARRAYBOUND { ULONG cElements; // Число элементов в данном измерении LONG lLBound; // Нижняя граница по данному измерению } SAFEARRAYBOUND;

Тип данных SAFEARRAY – функции поддержки SafeArrayCreate SafeArrayAccessData SafeArrayGetDim SafeArrayGetElement SafeArrayCopy SafeArrayRedim SafeArrayUnaccessData SafeArrayGetLBound SafeArrayGetRBound SafeArrayDestroy

Раннее связывание *.cpp*.h *.exe cmpnt.dll Компиляция и линковка

Позднее связывание pIX->GetIDsOfNames … pIX->Invoke … pIX->Invoke … *.exe

Позднее связывание Dim Bullwinkle As Object Set Bullwinkle = CreateObject(TalkingMoose) Bullwinkle.PullFromHat 1, Topolino

Библиотеки типа Хранят в бинарном виде информацию о компонентах интерфейсах методах свойствах аргументах структурах

Создание библиотеки типа 1. ::CreateTypeLib(), ICreateTypeLib 2. IDL и компилятор MIDL

Библиотека типа в IDL // Интерфейс IX [ object, uuid(32BB8326-B41B-11CF-A6BB-0080C7B2D682), helpstring("Интерфейс IX"), pointer_default(unique), dual, oleautomation ] interface IX : IDispatch { import "oaidl.idl"; HRESULT FxStringIn([in] BSTR bstrIn); HRESULT FxStringOut([out, retval] BSTR* pbstrOut); };

Библиотека типа в IDL // Описание компонента и библиотеки типа [ uuid(D3011EE1-B997-11CF-A6BB-0080C7B2D682), version(1.0), helpstring("Основы COM, Глава Библиотека типа") ] library ServerLib { importlib("stdole32.tlb"); // Компонент [ uuid(0C092C2C-882C-11CF-A6BB-0080C7B2D682), helpstring("Класс компонента") ] coclass Component { [default] interface IX; };

Использование библиотек типа LoadRegTypeLib LoadTypeLib LoadTypeLibFromResource RegisterTypeLib

Использование библиотеки типа HRESULT hr; // Динамически загрузить TypeInfo, если он еще не загружен if (m_pITypeInfo == NULL) { ITypeLib* pITypeLib = NULL; hr = ::LoadRegTypeLib(LIBID_ServerLib, 1, 0, // Номера версии 0x00, &pITypeLib); if (FAILED(hr)) { // Загрузить и зарегистрировать библиотеку типа hr = ::LoadTypeLib(wszTypeLibFullName, &pITypeLib); if(FAILED(hr)) { trace("Вызов LoadTypeLib неудачен", hr); return hr; } // Убедиться, что библиотека типа зарегистрирована hr = RegisterTypeLib(pITypeLib, wszTypeLibFullName, NULL); if(FAILED(hr)) { trace("Вызов RegisterTypeLib неудачен", hr); return hr; } } // Получить информацию типа для интерфейса объекта hr = pITypeLib->GetTypeInfoOfGuid(IID_IX, &m_pITypeInfo); pITypeLib->Release(); if (FAILED(hr)) { trace("Вызов GetTypeInfoOfGuid неудачен", hr); return hr; } }

Библиотеки типа в реестре

HKEY_CLASSES_ROOT\ CLSID\ {0C092C29-882C-11CF-A6BB- 0080C7B2D682}\ TypeLib

Генерация исключений 1. Реализуйте для своего компонента интерфейс ISupportErrorInfo с единственной функцией-членом: // ISupportErrorInfo virtual HRESULT __stdcall InterfaceSupportsErrorInfo(const IID& iid) { return (iid == IID_IX) ? S_OK : S_FALSE; } 2. В своей реализации IDispatch::Invoke вызовите SetErrorInfo(0, NULL) перед вызовом ITypeInfo::Invoke. 3. При возникновении исключительной ситуации вызовите CreateErrorInfo, чтобы получить указатель на интерфейс ICreateErrorInfo. 4. С помощью этого интерфейса предоставьте информацию об ошибке. 5. Наконец, получите указатель на интерфейс IErrorInfo и вызовите SetErrorInfo, передав ей в качестве второго параметра полученный указатель. Первый параметр зарезервирован и всегда равен 0. Все остальное дело ITypeInfo и клиента.

Генерация исключений - пример // Создать объект «Информация об ошибке» ICreateErrorInfo* pICreateErr; HRESULT hr = ::CreateErrorInfo(&pICreateErr); if (FAILED(hr)) { return E_FAIL; } // pICreateErr->SetHelpFile(...); // pICreateErr->SetHelpContext(...); pICreateErr->SetSource(L«LeherCOM.Test2"); pICreateErr->SetDescription( L"Это фиктивная ошибка, сгенерированная компонентом"); IErrorInfo* pIErrorInfo = NULL; hr = pICreateErr->QueryInterface(IID_IErrorInfo, (void**)&pIErrorInfo); if (SUCCEEDED(hr)) { ::SetErrorInfo(0L, pIErrorInfo); pIErrorInfo->Release(); } pICreateErr->Release(); return E_FAIL;

Маршалинг HKEY_CLASSES_ROOT\ Interfaces\ {32BB8326-B41B-11CF-A6BB-0080C7B2D682}\ ProxyStubClsid32 { C } HKEY_CLASSES_ROOT\ CLSID\ { C }\ InprocServer32 = OLEAUT32.DLL