В предыдущем разделе мы определили общедоступный управляемый класс ManagedClass, который автоматически был представлен интерфейсом модели компонентных объектов Microsoft (COM), сгенерированным со значением AutoDual (Автодуальный), заданным в атрибуте Classlnterface (ClassInterfaceType: :AutoDual). Указанный дуальный интерфейс дал возможность клиенту получать доступ к классу ManagedClass. Это — удобная техника, хотя и несколько необычная, так как не существует способа задать версию для сгенерированного интерфейса, и создается только единственный интерфейс, который может быть в чем-то ограниченным. Здесь мы рассмотрим альтернативу значению AutoDual (Автодуальный), которая позволит создавать версии интерфейсов, но потребует точного определения интерфейса в программе. Для этого мы зададим значение None (Никакой) для атрибута Classlnterface (ClassInterfaceType: :None). Следующая программа демонстрирует управляемый компонент с явным образом описанными интерфейсом и глобально уникальными идентификаторами соклассов
//SomeManagedClass.срр
fusing <mscorlib.dll>
using namespace System;
// использование пространства имен Система;
using namespace System::Runtime::InteropServices;
// использование пространства имен
// Система::Время выполнения::InteropServices;
namespace SomeManagedClass
// пространство имен SomeManagedClass
Следующий код (который является программой на неуправляемом C++, созданной в Visual C++ 6.0) представляет собой клиент на основе модели компонентных объектов Microsoft (COM), который работает с описанным выше управляемым компонентом. И снова глобально уникальные идентификаторы жестко запрограммированы, а не генерируются оператором импорта библиотеки типов. Таким образом, в этом примере мы не используем утилиту Tlsexp.exe для генерации библиотеки типов Это сделало пример более наглядным для ситуации, когда приходится использовать существующий клиент, разработанный на основе модели компонентных объектов Microsoft (СОМ), без каких-либо его изменений. Другими словами, мы создали компонент на управляемом C++, который будет использоваться в качестве компонента на основе модели компонентных объектов Microsoft (COM) существующим клиентом, построенным на основе модели компонентных объектов Microsoft (COM), без повторной компиляции.
//COMClientOfManagedClass.срр
#include <unknwn.h> ttinclude <iostream.h>
// (8D48DE87-048E-466e-95C3-06F3C21FCEAA}
static const GUID CLSID_ManagedClass =
// статическая константа
{
Ox8D48DE87, Ox048E, Ox466e,
{
0x95, ОхСЗ, 0x06, OxF3, OxC2, OxlF, OxCE, OxAA
}
};
// {C3894DE3-F5D6-46fe-84C7-C6DDOE801C86}
static const GUID IID_IManagedClass =
// статическая константа
{
OxC3894DE3, OxF5D6, Ox46fe,
{
0x84, OxC7, OxC6, OxDD, OxOE, 0x80, OxlC, 0x86 )
};
class IManagedClass : public IDispatch
{
public:
virtual HRESULT _stdcall AddEmUp( // виртуальный
long a,
long b,
long* psum) = 0;
};
void main()
{
HRESULT hResult; IManagedClass *pimc;
hResult = (reinitialize (NULL) ; // ПУСТОЙ УКАЗАТЕЛЬ
if (hResult != S_OK) return;
hResult = CoCreatelnstance (
CLSID_ManagedClass,
NULL, // ПУСТОЙ УКАЗАТЕЛЬ
CLSCTX_ALL,
IID_IManagedClass,
(void **) Spimc ) ;
if (hResult == REGDB_E_CLASSNOTREG) cout
"ERROR: CLSID is not properly registered.\n"
// "ОШИБКА: CLSID должным образом не зарегистрирован \п"
flush; // сброс
if (hResult == S_OK) {
cout "CoCreatelnstance succeeded.\n"
flush; long sum; // сумма
hResult = pimc->AddEmUp(3, 4, &sum); // должно быть 6
if (hResult == S_OK)
cout « "AddEmUp(3,4) is: " « sum « endl « flush; // «сумма
endl сброс; pimc->Release();
}
CoUninitialize ();
}
Ниже приведена выдача этой программы:
CoCreatelnstance succeeded.
AddEmUp(3,4) is: 7
Press any key to continue