содержит один параметр – каноническую текстовую форму
GUID: [object, uuid(BDA4A270-A1BA-11dO-8C2C-0080C73925BA)]
interface ICalculator : IBaseInterface
{
HRESULT Clear(void);
HRESULT Add([in] long n);
HRESULT Sum([out, retval] long *pn);
}
При использовании при программировании на С или C++ физического имени интерфейса IID данного интерфейса представляет собой просто логическое имя интерфейса, предшествуемое префиксом IID_. Например, интерфейс ICalculator будет иметь IID, которым можно программно манипулировать, используя сгенерированную IDL константу IID_ICalculator. Для предотвращения коллизий между символическими именами интерфейсов можно использовать пространство имен C++.
Поскольку лишь немногие из компиляторов C++ могут поддерживать 128-битные числа, СОМ определяет С-структуру для представления 128-битовой величины GUID и предлагает псевдонимы для типов IID и CLSID с использованием следующего определения типов:
typedef struct
Внутренняя структура GUID для большинства программистов несущественна, так как единственная значимая операция, которую можно выполнить с GUID, – это проверка их эквивалентности. Для обеспечения эффективной передачи величин GUID как аргументов функций СОМ предусматривает также постоянные псевдонимы для ссылок (constant reference aliases) для каждого типа GUID:
#define REFGUID const GUID&
#define REFIID const IID&
#define REFCLSID const CLSID&
Чтобы иметь возможность сравнивать величины GUID, СОМ обеспечивает функции эквивалентности и перегружает операторы
inline BOOL IsEqualGUID(REFGUID r1, REFGUID r2)
{
return !memcmp(&r1, &r2, sizeof(GUID));
}
#def1ne IsEqualIID(r1, r2) IsEqualGUID((r1) , (r2))
#define IsEqualCLSID(r1, r2) IsEqualGUID((r1), (r2))
inline BOOL operator == (REFGUID r1, REFGUID r2)
{
return !memcmp(&r1, &r2, sizeof(GUID));
}
inline BOOL operator != (REFGUID r1, REFGUID r2)
{
return !(r1 == r2);
}
Фактические заголовки SDK содержат условно компилируемые совместимые с С версии определений типа, макросов и встраиваемых функций, как показано выше.
Поскольку показано, что представления имен интерфейсов на этапе выполнения являются GUID, а не строками; это означает, что метод Dynamic_Cast, описанный в предыдущей главе, следует пересмотреть. Действительно, весь интерфейс IЕхtensibleObject должен быть изменен и преобразован в свой аналог IUnknown, совместимый с СОМ.
Интерфейс IUnknown
СОМ-интерфейс IUnknown имеет то же назначение, что и интерфейс IExtensibleObject, определенный в предыдущей главе. Последняя версия IExtensibleObject, появившаяся в конце предыдущей главы, имеет вид:
class IExtensibleObject
{
public:
virtual void *Dynamic_Cast(const char* pszType) = 0;
virtual void DuplicatePointer(void) = 0;
virtual void DestroyPointer(void) = 0;
}
Для определения типа на этапе выполнения был применен метод Dynamic_Cast, аналогичный оператору C++ dynamic_cast. Для извещения объекта о том, что указатель интерфейса дублировался, использовался метод DuplicatePointer. Для сообщения объекту, что указатель интерфейса уничтожен и все