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



// invoke method

// вызываем метод HRESULT hr = p->SetString(bstr);

// free BSTR

// освобождаем BSTR SysFreeString(bstr);


Промежуточный класс для работы с BSTR, _UBSTR, включен в заголовочный файл ustring.h:


// from ustring.h (book-specific header file)

// из ustring.h (специфический для данной книги заголовочный файл)

class _UBSTR

{

BSTR m_bstr;

public:

_UBSTR(const char *psz) : m_bstr(SysAllocStringLen(0, strlen(psz)))

{

mbstowcs(m_bstr, psz, INT_MAX);

}

_UBSTR(const wchar_t *pwsz) : m_bstr(SysAllocString(pwsz))

{

}

operator BSTR (void) const

{ return m_bstr; }

~_UBSTR(void)

{ SysFreeString(m_bstr); }

};


При наличии такого промежуточного класса предыдущий фрагмент кода значительно упростится:


// invoke method

// вызываем метод

HRESULT hr = p->SetString(_UBSTR(OLESTR(«Hello»)));


Заметим, что в промежуточном классе UBSTR могут быть в равной степени использованы строки типов char и wchar_t.

При передаче из метода строк через параметры типа [out] объект обязан вызвать SysAllocString, чтобы записать результирующую строку в буфер. Затем вызывающий объект должен освободить буфер путем вызова SysFreeString. Рассмотрим следующее определение метода:


HRESULT GetString([out, retval] BSTR *pbstr);


При реализации метода потребуется создать новую BSTR-строку для возврата вызывающему объекту:


STDMETHODIMP MyClass::GetString(BSTR *pbstr)

{

*pbstr = SysAllocString(OLESTR(«Coodbye!»)) ;

return S_OK;

}


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


extern OLECHAR g_wsz[];

BSTR bstr = 0;

HRESULT hr = p->GetString(&bstr);

if (SUCCEEDED(hr))

{

wcscpy(g_wsz, bstr); SysFreeString(bstr);

}


Тут нужно рассмотреть еще один важный аспект BSTR. В качестве BSTR можно передать нулевой указатель, чтобы указать на пустую строку. Это означает, что предыдущий фрагмент кода не совсем корректен. Вызов wcscpy:


wcscpy(g_wsz, bstr);


должен быть защищен от возможных нулевых указателей:


wcscpy (g_wsz, bstr ? bstr : OLESTR(""));


Для упрощения использования BSTR в заголовочном файле ustring.h содержится простая встраиваемая функция:


intline OLECHAR *SAFEBSTR(BSTR b)

{

return b ? b : OLESTR("");

}


Разрешение использовать нулевые указатели в качестве BSTR делает тип данных более эффективным с точки зрения использования памяти, хотя и приходится засорять код этими простыми проверками.

Простые типы, показанные на рис. 2.6, могут компоноваться вместе с применением структур языка С. IDL подчиняется правилам С для пространства имен тегов (tag namespace). Это означает, что большинство IDL-определений интерфейсов либо используют операторы определения типа (typedef):