Дональд Бокс - Сущность технологии СОМ. Библиотека программиста
- Название:Сущность технологии СОМ. Библиотека программиста
- Автор:
- Жанр:
- Издательство:Питер
- Год:2001
- Город:СПб
- ISBN:5-318-00058-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Дональд Бокс - Сущность технологии СОМ. Библиотека программиста краткое содержание
В этой книге СОМ исследуется с точки зрения разработчика C++. Написанная ведущим специалистом по модели компонентных объектов СОМ, она раскрывает сущность СОМ, помогая разработчикам правильно понять не только методы модели программирования СОМ, но и ее основу. Понимание мотивов создания СОМ и ее аспектов, касающихся распределенных систем, чрезвычайно важно для тех разработчиков, которые желают пойти дальше простейших приложений СОМ и стать по-настоящему эффективными СОМ-программистами. Показывая, почему СОМ для распределенных систем (Distributed СОМ) работает именно так, а не иначе, Дон Бокс дает вам возможность применять эту модель творчески и эффективно для ежедневных задач программирования.
Сущность технологии СОМ. Библиотека программиста - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
{
m_szName[0] = 0;
hr = E_INVALIDARG;
} return hr;
}
};
Соответствующие перегруженные функции для процедур strlen, strcpy и strcat также включены в заголовочный файл ustring.h.
Использование перегрузки библиотечных функций для копирования строк из одного буфера в другой, как это показано выше, обеспечивает лучшее качество исполнения, уменьшает размер кода и непроизводительные издержки программиста. Однако часто возникает ситуация, когда одновременно используются СОМ и API-функции Win32, что не дает возможности применить эту технику. Рассмотрим следующий фрагмент кода, читающий строку из элемента редактирования и преобразующий ее в IID:
HRESULT IIDFromHWND(HWND hwnd, IID& riid)
{
TCHAR szEditText[1024];
// call a TCHAR-based Win32 routine
// вызываем TCHAR-процедуру Win32
GetWindowText(hwnd, szEditText, 1024);
// call an OLECHAR-based СОМ routine
// вызываем OLECHAR-процедуру СОМ
return IIDFromString(szEditText, &riid);
}
Допуская, что этот код скомпилирован с указанным символом С-препроцессора UNICODE; он работает безупречно, так как TCHAR и OLECHAR являются просто псевдонимами wchar_t и никакого преобразования не требуется. Если же функция скомпилирована с версией Win32 API, не поддерживающей Unicode, то TCHAR является псевдонимом для char, и первый параметр для IIDFromString имеет неправильный тип. Чтобы решить эту проблему, нужно провести условную компиляцию:
HRESULT IIDFromHWND(HWND hwnd, IID& riid)
{
TCHAR szEditText[1024];
GetWindowText(hwnd, szEditText, 1024);
#ifdef UNICODE return IIDFromString(szEditText, &riid);
#else OLECHAR wszEditText[l024];
ustrncpy(wszEditText, szEditText, 1024);
return IIDFromString(wszEditText, &riid);
#endif
}
Хотя этот фрагмент и генерирует оптимальный код, очень утомительно применять эту технику всякий раз, когда символьный параметр имеет неверный тип. Можно справиться с этой проблемой, если использовать промежуточный (shim) класс с конструктором, принимающим в качестве параметра любой тип символьной строки. Этот промежуточный класс должен также содержать в себе операторы приведения типа, что позволит использовать его в обоих случаях: когда ожидается const char * или const wchar_t *. В этих операциях приведения промежуточный класс либо выделяет резервный буфер и производит необходимое преобразование, либо просто возвращает исходную строку, если преобразования не требовалось. Деструктор промежуточного класса может затем освободить все выделенные буферы. Заголовочный файл ustring.h содержит два таких промежуточных класса: _U и _UNCC. Первый предназначен для нормального использования; второй используется с функциями и методами, тип аргументов которых не включает спецификатора const [2](таких как IIDFromString). При возможности применения двух промежуточных классов предыдущий фрагмент кода может быть значительно упрощен:
HRESULT IIDFromHWND(HWND hwnd, IID& riid)
{
TCHAR szEditText[1024];
GetWindowText(hwnd, szEditText, 1024);
// use _UNCC shim class to convert if necessary
// используем для преобразования промежуточный класс _UNCC,
// если необходимо
return IIDFromString(_UNCC(szEditText), &riid);
}
Заметим, что не требуется никакой условной компиляции. Если код скомпилирован с версией Win32 с поддержкой Unicode, то класс _UNCC просто пропустит исходный буфер через свой оператор приведения типа. Если же код компилируется с версией Win32, не поддерживающей Unicode, то класс _UNCC выделит буфер и преобразует строку в Unicode. Затем деструктор _UNCC освободит буфер, когда операция будет выполнена полностью [3].
Следует обсудить еще один дополнительный тип данных, связанный с текстом, – BSTR. Строковый тип BSTR нужно применять во всех интерфейсах, которые предполагается использовать из языков Visual Basic или Java. Строки BSTR являются OLECHAR-строками с префиксом длины (length-prefix) в начале строки и нулем в ее конце. Префикс длины показывает число байт , содержащихся в строке (исключая завершающий нуль) и записан в форме четырехбайтового целого числа, непосредственно предшествующего первому символу строки. Рисунок 2.7 демонстрирует BSTR на примере строки «Hi». Чтобы позволить методам свободно возвращать строки BSTR без заботы о выделении памяти, все BSTR размещены с помощью распределителя памяти, управляемого СОМ. В СОМ предусмотрено несколько API-функций для управления BSTR:

// from oleauto.h
// allocate and initialize a BSTR
// выделяем память и инициализируем строку BSTR
BSTR SysAllocString(const OLECHAR *psz);
BSTR SysAllocStringLen(const OLECHAR *psz, UINT cch);
// reallocate and initialize a BSTR
// повторно выделяем память и инициализируем BSTR
INT SysReAllocString(BSTR *pbstr, const OLECHAR *psz);
INT SysReAllocStringLen(BSTR *pbstr, const OLECHAR * psz, UINT cch);
// free a BSTR
// освобождаем BSTR void SysFreeString(BSTR bstr);
// peek at length-prefix as characters or bytes
// считываем префикс длины как число символов или байт
UINT SysStringLen(BSTR bstr);
UINT SysStringByteLen(BSTR bstr);
При пересылке строк методу в качестве параметров типа [in] вызывающий объект должен заботиться о том, чтобы вызвать SysAllocString прежде, чем запускать сам метод, и чтобы вызвать SysFreeString после того, как метод закончил работу. Рассмотрим следующее определение метода:
HRESULT SetString([in] BSTR bstr);
Пусть в вызывающей программе уже имеется строка, совместимая с OLECHAR, тогда для того, чтобы преобразовать строку в BSTR до вызова метода, необходимо следующее:
// convert raw OLECHAR string to a BSTR
// преобразовываем «сырую» строку OLECHAR в строку BSTR
BSTR bstr = SysAllocString(OLESTR(«Hello»));
// 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:
Читать дальшеИнтервал:
Закладка: