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

// GIT cookie – top/left

// «закладка» GIT для верхнего/левого элемента

GIP(IPoint) m_gipBottomRight;

// GIT cookie – bottom/right

// «закладка» GIT для нижнего/правого элемента

:

:

:

}

Для инициализации элемента GlobalInterfacePointer разработчик (который выполняется в апартаменте объекта) просто регистрирует обрабатываемые указатели, вызывая метод Globalize на каждый GlobalInterfacePointer:

SafeRect::SafeRect(void) : m_cRef (0), m_pUnkFTM(0) {

IPoint *pPoint = 0;

// create instance of class Point

// создаем экземпляр класса Point

HRESULT hr = CoCreateInstance(CLSID_Point, 0, CLSCTX_INPROC, IID_Ipoint, (void**)&pPoint);

assert (SUCCEEDED(hr));

// register interface pointer in GIT

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

hr = m_gipTopLeft.Globalize(pPoint);

assert (SUCCEEDED(hr));

pPoint->Release;

// reference is now held in GIT

// теперь ссыпка хранится в GIT

// create instance of class Point

// создаем экземпляр класса Point

hr = CoCreateInstance(CLSID_Point, 0, CLSCTX_INPROC, IID_Iроint, (void**) &рРоint);

assert(SUCCEEDED(hr));

// register interface pointer in GIT

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

hr = m_gipBottomRight.Globalize(pPoint);

assert (SUCCEEDED (hr));

pPoint->Release;

// reference is now held in GIT

// теперь ссылка хранится в GIT

}

Те методы, которым нужен доступ к глобализованным указателям, могут импортировать локальную копию посредством метода Localize из GlobalInterfaсePointer:

STDMETHODIMP SafeRect::get_Top(long *pVal) {

IPoint *pPoint = 0;

// local imported pointer

// локальный импортированный указатель

HRESULT hr = m_gipTopLeft.Localize(&pPoint);

if (SUCCEEDED(hr)){

long x;

hr = pPoint->get_Coords(&x, pVal);

pPoint->Release; }

return hr;

}

Отметим, что в силу применения маршалера свободной поточной обработки (FreeThreaded Marshaler) исходный интерфейсный указатель не может быть кэширован, а должен импортироваться при каждом вызове метода, чтобы предотвратить попытку доступа из неверного апартамента.

Предыдущий фрагмент кода может быть автоматизирован еще больше. Поскольку большинство вызовов методов в классе GlobalInterfacePointer должны будут локализовать временный указатель в самом вызове метода, то приводимый ниже класс автоматизирует импорт временного указателя и его последующее освобождение, что очень напоминает интеллектуальный указатель (smart pointer):

template class LocalInterfacePointer {

Itf *m_pItf;

// temp imported pointer

// временный импортированный указатель

// prevent misuse

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

LocalInterfacePointer(const LocalInterfacePointer&);

operator = (const LocalInterfacePointer&);

public:

LocalInterfacePointer(const GlobalInterfacePointer& rhs, HRESULT& hr) { hr = rhs.Loca1ize(&m_pItf) ; }

LocalInterfacePointer(DWORD dwCookie, HRESULT& hr) { assert(g_pGIT != 0);

hr = g_pGIT-&gtGetInterfaceFromGlobal(dwCookie, *piid, (void**)&m_pItf); }

~LocalInterfacePointer(void) { if (m_pItf) m_pItf->Release; }

class SafeItf : public Itf { STDMETHOD_(ULONG, AddRef) (void) = 0;

// hide

// скрытый STDMETHOD_(ULONG, Release)(void) = 0;

// hide

// скрытый

};

SafeItf *GetInterface(void) const { return (SafeItf*) m_pItf; }

SafeItf *operator ->(void) const { assert(m_pItf != 0);

return GetInterface;

}

};

#def1ne LIP(Itf) LocalInterfacePointer

С получением этого второго класса C++ обработка импортированных указателей становится намного проще:

STDMETHODIMP SafeRect::get_Area(long *pn) {

long top, left, bottom, right;

HRESULT hr, hr2;

// import pointers

// импортируем указатели

LIP(IPoint) lipTopLeft(m_gipTopLeft, hr);

LIP(IPoint) lipBottomRight(m_gipBottomRight, hr2);

assert(SUCCEEDED(hr) && SUCCEEDED(hr2));

// use temp tocal pointers

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

hr = lipTopLeft->GetCoords(&left, ⊤);

hr2 = lipBottomRight->GetCoords(&right, ⊥);

assert(SUCCEEDED(hr) && SUCCEEDED(hr2));

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

// LocalInterfacePointer auto-releases temp ptrs.

// LocalInterfacePointer сам освобождает

// временные указатели

}

Макросы GIP и LIP делают совместное использование GIT и FTM намного менее громоздким. До появления GIT использование FTM в классе с интерфейсными указателями было значительно более трудным, чем теперь обеспечивает любой из кодов, приведенных в данном разделе.

<p>Где мы находимся?</p>
Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже