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); }
Клиенты получают доступ к
Для того чтобы сделать интерфейсный указатель доступным для всех апартаментов процесса, апартамент, содержащий этот интерфейсный указатель, должен зарегистрировать его в
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; }
Отметим принципиальную разницу между этими фрагментами кода и примерами с применением
Архитектура стандартного маршалинга