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

HRESULT RegisterInterfaceInGlobal ( [in, iid_is(riid)] IUnknown *pItf, [in] REFIID riid, [out] DWORD *pdwCookie);

// destroy the marshaled object reference

// уничтожаем маршалированную объектную ссылку

HRESULT RevokeInterfaceFromGlobal ( [in] DWORD dwCookle);

// unmarshal an interface from the GIT

// демаршалируем интерфейс из GIT

HRESULT GetInterfaceFromGlobal ( [in] DWORD dwCookie, [in] REFIID riid, [out, iid_is(riid)] void **ppv); }

Клиенты получают доступ к GIT для своего процесса, вызывая CocreateInstance с использованием класса CLSID_StdGlobalInterfaceTable. Каждый вызов CoCreateInstance с применением этого CLSID возвращает указатель на одну и ту же GIT в процессе. Так же как к интерфейсу IStream, возвращенному CoMarshalInterThreadInterfaceInStream, к интерфейсным указателям на GIT можно обратиться из любого апартамента без обязательного маршалинга.

Для того чтобы сделать интерфейсный указатель доступным для всех апартаментов процесса, апартамент, содержащий этот интерфейсный указатель, должен зарегистрировать его в GIT путем вызова метода RegisterInterfaceInGlobal. GIT вернет вызывающей программе DWORD, который представляет глобальный указатель для всех апартаментов процесса. Этот DWORD может быть использован из любого апартамента процесса для демаршалинга нового заместителя путем вызова метода GetInterfaceFromGlobal. Этот же DWORD можно использовать для повторного демаршалинга заместителей до тех пор, пока вызов RevokeInterfaceFromGlobal не объявит глобальный интерфейсный указатель недействительным. Приложения, использующие эту глобальную интерфейсную таблицу (GIT ), обычно связывают один интерфейсный указатель на весь процесс при запуске:

IGlobalInterfaceTable *g_pGIT = 0; HRESULT Init0nce(void) {

assert(g_pGIT == 0);

return CoCreateInstance(CLSID_StdGlobalInterfaceTable, 0, CLSCDX_INPROC_5ERVER, IID_IGlobalInterfaceTable, (void**)&g_pGIT);

}

Когда глобальная интерфейсная таблица является доступной, передача интерфейсного указателя в другой апартамент сводится к простой регистрации указателя в глобальной интерфейсной таблице:

HRESULT WritePtrToGlobalVariable(IRacer *pRacer) {

// where to write the marshaled ptr

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

DWORD g_dwCookie;

// thread synchronization

// синхронизация потока extern HANDLE g_heventWritten;

// write marshaled object reference to global variable

// записываем маршалированную объектную ссыпку в глобальную переменную

HRESULT hr = g_pGIT->RegisterInterfaceInGlobal( pRacer, IID_IRacer, &g_dwCookie);

// signal other thread that ptr is now available

// сообщаем другому потоку о доступности указателя SetEvent(g_heventWritten); return hr; }

Следующий код корректно демаршалирует объектную ссылку и может вызываться из любого апартамента одного и того же процесса:

HRESULT ReadPtrFromGlobalVariable(IRacer * &rpRacer, bool bLastUnmarshal) {

// where to write the marshaled ptr

// куда записывать маршалированный указатель extern DWORD g_dwCookie;

// thread synchronization

// синхронизация потока extern

HANDLE g_heventWritten;

// wait for other thread to signal that ptr is available

// ожидаем другой поток, чтобы сигнализировать о доступности указателя

WaitForSingleObject(g_heventWritten, INFINITE);

// read marshaled object reference from global variable

// читаем маршалированную объектную ссылку из глобальной переменной

HRESULT hr = g_pGIT->GetInterfaceFromGlobal( g_dwCookie, IID_IRacer, (void**)&rpRacer);

// if we are the last to unmarshal, revoke the pointer

// если мы поспедние в очереди на демаршалинг, то

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

if (bLastUnmarshal) g_pGIT->RevokeInterfaceFromGlobal(g_dwCookie);

return hr; }

Отметим принципиальную разницу между этими фрагментами кода и примерами с применением CoMarshalInterThreadInterfaceInStream. Она состоит в том, что код, основанный на GIT, способен демаршалировать более чем один заместитель.

<p>Архитектура стандартного маршалинга</p>
Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже