Сущность технологии COM



         

Вспомогательные средства для внутрипроцессного маршалинга


Хотя фрагменты кода для WritePtr и ReadPtr из предыдущего раздела достаточно просто реализовать, большинство явных вызовов CoMarshalInterface будут использоваться для передачи интерфейсного указателя от одного потока к другому в том же самом процессе. Для упрощения этой задачи в СОМ предусмотрены две оберточные функции (wrapper functions), которые реализуют нужный стандартный код вокруг CoMarshalInterface и CoUnmarshalInterface. API-функция СОМ CoMarshalInterThreadInterfaceInStream

HRESULT CoMarshalInterThreadInterfaceInStream( [in] REFIID riid, [in, iid_is(riid)] IUnknown *pItf, [out] IStream **ppStm );

обеспечивает простую обертку вокруг CreateStreamOnHGlobal и CoMarshalInterface, как показано ниже:

// from OLE32.DLL (approx.) // из OLE32.DLL (приблизительно) HRESULT CoMarshalInterThreadInterfaceInStream( REFIID riid, IUnknown *pItf, IStream **ppStm) { HRESULT hr = CreateStreamOnHGlobal(0, TRUE, ppStm); if (SUCCEEDED(hr)) hr = CoMarshalInterface(*ppStm, riid, pItf, MSHCTX_INPROC, 0, MSHLFLAGS_NORMAL); return hr; }

В СОМ предусмотрена также обертка вокруг CoUnmarshalInterface:

HRESULT CoGetInterfaceAndReleaseStream( [in] IStream *pStm, [in] REFIID riid, [out, iid_is(riid)] void **ppv );

которая является очень тонкой оберткой вокруг CoUnmarshalInterface:

// from OLE32.DLL (approx.) // из OLE32.DLL (приблизительно) HRESULT CoGetInterfaceAndReleaseStream( IStream *pStm, REFIID riid, void **ppv) { HRESULT hr = CoUnmarshalInterface(pStm, riid, ppv); pStm->Release(); return hr; }

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

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

HRESULT WritePtrToGlobalVarable(IRacer *pRacer) { // where to write the marshaled ptr // куда записывать маршалированный указатель extern IStream *g_pStmPtr; // thread synchronization for read/write // синхронизация потока для чтения/записи extern HANDLE g_heventWritten; // write marshaled object reference to global variable // записываем маршалированную объектную ссыпку // в глобальную переменную HRESULT hr = CoMarshalInterThreadInterfaceInStream( IID_IRacer, pRacer, &g_pStmPtr); // signal other thread that ptr is now available // подаем сигнал другому процессу о том, что указатель // теперь доступен SetEvent (g_heventWritten); return hr; }




Содержание  Назад  Вперед