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

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

Преимуществом специального маршалинга является то, что клиент не имеет понятия о его использовании. Фактически клиент не может достоверно определить, является ли интерфейс стандартным заместителем, специальным заместителем или настоящим объектом. Специальный маршалинг является решением на уровне объект-объект. Два экземпляра одного и того же класса могут независимо друг от друга избрать стандартный или специальный маршалинг. Если объект выбирает реализацию специального маршалинга, то он должен делать это для всех интерфейсов. Если объект желает специально маршалировать только для части всех возможных контекстов, подлежащих маршалингу – например, внутрипроцессный, локальный, с другой машины, – то он может получить экземпляр стандартного маршалера и направить его методы IMarshal для маршалинга неподдерживаемых контекстов, так чтобы могли поддерживаться все контексты. Если бы объект мог безоговорочно направить все методы IMarshal к стандартному маршалеру, то он практически всегда использовал бы стандартный маршалинг.

Для получения указателя на стандартный маршалер объекты могут вызывать метод CoGetStandardMarshal:

HRESULT CoGetStandardMarshal( [in] REFIID riid,

// type of itf marshaled?

// тип, которым маршалирован интерфейс?

[in, iid_is(riid)] IUnknown *pUnk,

// the itf to marshal

// интерфейс для маршалинга

[in] DWORD dwDestCtx,

// MSHCTX [in] void *pvDestCtx,

// reserved // зарезервировано [in] DWORD mshlflags,

// normal vs. table // нормальный или табличный маршалинг

[out] IMarshal **ppMarshal); // ptr to std. Marshal

// указатель на стандартный маршалер

Предположим, что объект использует технологию специального маршалинга, которая работает только на локальном хосте, но не при связи с внехостовыми апартаментами. Реализация объектом метода GetMarshalSizeMax могла бы выглядеть примерно так:

STDMETHODIMP CustStd::GetMarshalSizeMax(

ULONG *pcb, REFIID riid, void *pv, DWORD dwDestCtx, void *pvDestCtx, DWORD mshlflags) {

// if context is supported, do work!

// если контекст поддерживается, то действуем!

if (dwDestCtx == MSHCTX_LOCAL || dwDestCtx == MSHCTX_INPROC) return this->MyCustomMarshalingRoutine(pcb);

// unsupported context, delegate to std marshal

// контекст не поддерживается, обращаемся к стандартному маршапингу

IMarshal *pMsh = 0;

HRESULT hr = CoGetStandardMarshal (riid, pv, dwDestCtx, pvDestCtx, mshlflags, &pMsh);

if (SUCCEEDED(hr)) {

hr = pMsh->GetMarshalSizeMax(pcb, riid, pv, dwDestCtx, pvDestCtx, mshlflags);

pMsh->Retease();

}

return hr;

}

В этом фрагменте кода не показано, как писать инициализационное сообщение для случая, когда действительно желателен специальный маршалинг. Дело в том, что не существует стандартной реализации каждого из методов IMarshal (отсюда и термин специальный (custom) маршалинг). Существует, однако, несколько общих сценариев, в которых специальный маршалинг чрезвычайно выигрышен и реализация IMarshal в этих сценариях – довольно обычное явление. Безусловно, наиболее общим приложением IMarshal является реализация маршалинга по значению (marshal-by-value).

Маршалинг по значению наиболее удобен для таких объектов, которые после инициализации никогда не изменяют своего состояния. Обертки СОМ для структур – вот типичный пример объекта, который просто инициализирован, передан другому объекту для запроса и затем уничтожен. Такой объект является первым кандидатом для специального маршалинга. При реализации маршалинга по значению реализация объекта почти всегда является внутрипроцессным сервером. Это позволяет объекту и заместителю разделять один и тот же класс реализации. Идея маршалинга по значению состоит в том, что специальный заместитель становится клоном исходного объекта. Из этого следует, что маршалированная объектная ссылка должна содержать все состояние исходного объекта, а также (для простоты) то, что CLSID специального заместителя должен быть тем же, что и у исходного объекта.

Представим следующее определение класса СОМ-обертки вокруг простой двумерной точки:

class Point : public IPoint, public IMarshal

{

long m_x;


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