Сущность технологии СОМ. Библиотека программиста

ОглавлениеДобавить в закладки К обложке

STDMETHODIMP SafeRect::get_Area(long *pn) {

extern IGlobalInterfaceTable *g_pGIT; assert(g_pGIT != 0);

// unmarshal the two interface pointers from the GIT

// демаршалируем дВа интерфейсных указателя из GIT

IPoint *ptl = 0, *pbr = 0;

HRESULT hr = g_pGIT->GetInterfaceFromGlobal(m_dwPtTopLeft, IID_Ipoint, (void**)&ptl);

assert (SUCCEEDED(hr));

hr = g_pGIT->GetInterfaceFromGlobal(m_dwPtBottomRight, IID_Ipoint, (void**)&pbr);

// use temp ptrs to implement method

// дпя реализации метода используем временные указатели

long top, left, bottom, right;

hr = ptl->GetCoords(&left, &top);

assert (SUCCEEDED(hr));

hr = pbr->GetCoords(&right, &bottom);

assert (SUCCEEDED (hr));

*pn = (right – left) * (bottom – top);

// release temp ptrs. // освобождаем временные указатели

ptl->Release();

pbr->Release();

return S_OK;

}

Поскольку реализация SafeRect использует FTM, то нецелесообразно пытаться сохранить немаршалированные интерфейсные указатели между вызовами метода, так как неизвестно, произойдет ли следующий вызов метода в том же самом апартаменте.

Все зарегистрированные интерфейсные указатели будут храниться в таблице GIT до тех пор, пока они не будут явно удалены нз GIT. Это означает, что класс SafeRect должен явно аннулировать элементы GIT для двух своих элементов данных:

SafeRect::~SafeRect(void) {

extern IGlobalInterfaceTable *g_pGIT;

assert(g_pGIT != 0);

HRESULT hr = g_pGIT->RevokeInterfaceFromGlobal(m_dwTopLeft);

assert(SUCCEEDED(hr));

hr = g_pGIT->RevokeInterfaceFromGlobal(m_dwBottomRight);

assert(SUCCEEDED(hr));

}

Удаление интерфейсного указателя из GIT освобождает все хранящиеся ссылки на объект.

Отметим, что совместное использование GIT и FTM влечет за собой очень много обращений к GIT, которые будут сделаны для создания временных интерфейсных указателей, необходимых для использования в каждом отдельном методе. Хотя GIT оптимизирована именно для поддержки такой схемы использования, код остается однообразным. Следующий простой класс C++ скрывает использование «закладки» GIT за удобным интерфейсом, обеспечивающим безопасность типа:

template <class Itf, const IID* piid> class GlobalInterfacePointer {

DWORD m_dwCookie;

// the GIT cookie

// «закладка» GIT

// prevent misuse

// предотвращаем неправильное использование

GlobalInterfacePointer(const GlobalInterfacePointer&);

void operator =(const GlobalInterfacePointer&);

public:

// start as invalid cookie

// начинаем как неправильная «закладка»

GlobalInterfacePointer(void) : m_dwCookie(0) { }

// start with auto-globalized local pointer

// начинаем с автоматически глобализованным локальным указателем

GlobalInterfacePointer(Itf *pItf, HRESULT& hr) : m_dwCookie(0)

{ hr = Globalize(pItf); }

// auto-unglobalize

// осуществляем автоматическую деглобапизацию

~GlobalInterfacePointer(void) { if(m_dwСооkiе) Unglobalize() ; }

// register an interface pointer in GIT

// регистрируем интерфейсный указатель в GIT

HRESULT Globalize(Itf *pItf) { assert (g_pGIT != 0 && m_dwCookie == 0);

return g_pGIT->RegisterInterfaceInGlobal(pItf, * piid, &m_dwCookie);

}

// revoke an interface pointer in GIT

// аннулируем интерфейсный указатель в GIT

HRESULT Unglobalize(void) {

assert(g_pGIT != 0 && m_dwCookie != 0);

HRESULT hr = g_pGIT->RevokeInterfaceFromGlobal(m_dwCookie);

m_dwCookie = 0;

return hr;

}

// get а local interface pointer from GIT

// получаем локальный интерфейсный указатель из GIT

HRESULT Localize(Itf **ppItf) const {

assert(g_pGIT != 0 && m_dwCookie != 0);

return g_pGIT->GetInteгfaceFromGlobal(m_dwCookie, *piid, (void**)ppItf);

}

// convenience methods

// методы для удобства

bool IsOK(void) const { return m_dwCookie != 0; }

DWORD GetCookie(void) const { return m_dwCookie; }

};

#define GIP(Itf) GlobalInterfacePointer<Itf, &IID_##Itf>

Имея данное определение класса и макрос, класс SafeRect теперь вместо исходных DWORD сохраняет GlobalInterfacePointers:


Логин
Пароль
Запомнить меня