TN059: С помощью макросов MFC И MBCS преобразования Юникода
![]() |
---|
Следующая техническая заметка не была обновлена со времени сначала была включена в подключенной документации.В результате некоторые процедуры и разделы могут оказаться устаревшей или неверны.Последние новости, рекомендуется поиск раздела процента в подключенном индексу документации. |
Эта заметка описывает, как использовать макрос для преобразования MBCS в юникоде,/, которые определены в AFXPRIV.H.Эти макросы наиболее полезны, если приложение обрабатывает непосредственно с API OLE или по какой-то причине часто требуется выполнить преобразование между Юникодом и многобайтовой кодировкой.
Общие сведения
В MFC 3.x, специальные библиотеки DLL использовалось (MFCANS32.DLL), чтобы автоматически преобразовать между Юникодом и многобайтовой кодировкой, когда интерфейсы OLE были вызваны.Эта библиотека DLL был практически прозрачный уровнем, разрешившего ЯВЛЯЕТСЯ приложения следует записать, если интерфейсы API OLE и были многобайтовой кодировкой, даже если они всегда Юникод (за исключением на macintosh).Хотя этот уровень был удобные и разрешенные приложения быстро быть переношенным из Win16 на Win32 (MFC, Microsoft Word, Microsoft Excel и VBA, лишь некоторые из приложений, использующих эту технологию Майкрософт), она имела иногда значительно выполненную строку производительности.По этой причине MFC, 4.x не использует эту библиотеку DLL и не сообщает, а не напрямую для интерфейсов OLE в юникоде.Для этого MFC необходимо преобразовать в многобайтовой кодировке юникод в звоня к интерфейсу OLE и часто необходимо преобразовать в многобайтовой кодировке юникод, реализующим ole-интерфейс из.Чтобы обработать это легко и эффективно нескольких макросов, созданных для этого преобразования.
Один из самых больших барьеров создать набор макросов выделение памяти.Так как строки не могут быть преобразованы в месте, новая память для хранения преобразованных результаты должны быть выбраны.Это может быть сделано с кодом примерно следующим образом:
// we want to convert an MBCS string in lpszA
int nLen = MultiByteToWideChar(CP_ACP, 0,lpszA, -1, NULL, NULL);
LPWSTR lpszW = new WCHAR[nLen];
MultiByteToWideChar(CP_ACP, 0,
lpszA, -1, lpszW, nLen);
// use it to call OLE here
pI->SomeFunctionThatNeedsUnicode(lpszW);
// free the string
delete[] lpszW;
Этот подход как ряд проблем.Основная проблема заключается в том, что многие код для записи, тестирование и отладка.Какого-либо объекта, который был простым вызовом функции теперь более сложным.Кроме того, значительно служебные данные времени выполнения в этом.Должна быть выделена память в куче и освобождается каждый раз, когда выполняется преобразование.Наконец, код вышеуказанному было бы необходимо иметь соответствующее #ifdefs добавленное для построений в юникоде и macintosh (которые не требуют это преобразование выполняется).
Решение мы пришли вверх с создать некоторые макросы, 1) маска разницу между различными платформами и 2) для эффективной схема выделения памяти и 3) легко вставить в существующий код источника.Ниже приведен пример одного из определений:
#define A2W(lpa) (\
((LPCSTR)lpa == NULL) ? NULL : (\
_convert = (strnlen(lpa)+1),\
AfxA2WHelper((LPWSTR) alloca(_convert*2),
lpa, _convert)\
)\
)
Используя этот макрос вместо кода выше намного проще и вещи:
// use it to call OLE here
USES_CONVERSION;
pI->SomeFunctionThatNeedsUnicode(T2OLE(lpszA));
Дополнительные вызовы если необходимо преобразование, но помощью макросов просто и эффективно.
Реализация каждого макроса использует функции _alloca () для выделения памяти из стека вместо кучи.Выделение памяти из стека намного быстрее, чем при выборе память в куче, и память освобождается автоматически, когда функция выйденна.Кроме того, избегайте вызова макросов MultiByteToWideChar (или WideCharToMultiByte) несколько раз.Это делается путем выбора немного больше памяти, чем требуется.Мы знаем, что MBC по крайней мере одно преобразование в WCHAR и что для каждого WCHAR мы будет иметь не более 2 байт MBC.Выбрать несколько более чем требуемое, но всегда достаточно настроить преобразование избежать второго вызова втором вызове функции преобразования.Обращение к вспомогательному приложению функция AfxA2Whelper уменьшает число аргументов помещает, который необходимо выполнить, чтобы выполнить преобразование (это приводит к более небольшом коде, если оно вызвало MultiByteToWideChar непосредственно).
Для макросов, чтобы иметь место для хранения временной длина должна быть объявлена локальная переменная с именем _convert, делается в каждой функции, использующий макросы преобразования.Это осуществляется путем вызова макроса USES_CONVERSION как показано в примере выше.
Оба родовых макроса преобразования OLE конкретных и макросы.Эти 2 различных набора макроса описаны ниже.Все макросы находятся в AFXPRIV.H.
Родовые макросы преобразования
Макросы формируют базовый механизм родовые преобразования.Пример макроса и реализация, приведенные в предыдущем разделе, A2W, один такой универсальный шаблон» макрос «.Оно не связано с OLE в частности.Набор родовых макросов в списке ниже:
A2CW (LPCSTR) -> (LPCWSTR)
A2W (LPCSTR) -> (LPWSTR)
W2CA (LPCWSTR) -> (LPCSTR)
W2A (LPCWSTR) -> (LPSTR)
Помимо выполнения преобразования текста, также макросы и вспомогательная функция для преобразования TEXTMETRIC, DEVMODE, BSTR и выбранные OLE строки.Эти макросы вне области данного обсуждения – см. в разделе AFXPRIV.H дополнительные сведения об этих макросов.
Макросы преобразования OLE
Макросы преобразования OLE разработаны специально для обработки функции, которые ожидают символы OLESTR.При просмотре ЯВЛЯЕТСЯ заголовки, вы увидите несколько ссылок на LPCOLESTR и OLECHAR.Эти типы используются для обращения к типу символов, используемых в интерфейсах OLE, не относящихся к платформе.Сопоставления OLECHAR к char в платформе Win16 и macintosh и WCHAR в Win32.
Для хранения количества рекомендаций #ifdef в коде MFC минимальным доступны аналогичный макрос для каждого преобразования, где ЯВЛЯЕТСЯ строки.Следующие макросы наиболее часто используемым:
T2COLE (LPCTSTR) -> (LPCOLESTR)
T2OLE (LPCTSTR) -> (LPOLESTR)
OLE2CT (LPCOLESTR) -> (LPCTSTR)
OLE2T (LPCOLESTR) -> (LPCSTR)
Кроме того, подобные макросы для создания TEXTMETRIC, DEVMODE, BSTR и выбранные OLE строки.Дополнительные сведения см. в разделе AFXPRIV.H.
Другие вопросы
Не используйте макрос в плотном цикле.Например, требуется написать следующий тип кода:
void BadIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
for (int ii = 0; ii < 10000; ii++)
pI->SomeMethod(ii, T2COLE(lpsz));
}
Вышеуказанный код может привести к появлению выделение памяти в стеке мегабайты в зависимости от того, что содержимое строки lpsz !Он также принимает время преобразования строки для каждой итерации цикла.Вместо этого переместить такие постоянно преобразования из цикла:
void MuchBetterIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
LPCOLESTR lpszT = T2COLE(lpsz);
for (int ii = 0; ii < 10000; ii++)
pI->SomeMethod(ii, lpszT);
}
Если строка не является константой, инкапсулируйте вызов метода в функцию.Это позволяет буфер преобразования для освобождения каждый раз.Примеры.
void CallSomeMethod(int ii, LPCTSTR lpsz)
{
USES_CONVERSION;
pI->SomeMethod(ii, T2COLE(lpsz));
}
void MuchBetterIterateCode2(LPCTSTR* lpszArray)
{
for (int ii = 0; ii < 10000; ii++)
CallSomeMethod(ii, lpszArray[ii]);
}
Не возвращайте результат одного из макросов, если возвращаемое значение не будет подразумевать сделать копию данных перед пределами извлечения.Например, этот код неправильно.
LPTSTR BadConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR lpsz = NULL;
pI->GetFileName(&lpsz);
LPTSTR lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
return lpszT; // bad! returning alloca memory
}
Код, приведенный выше может быть зафиксирован, изменить возвращаемое значение для какого-либо объекта, который копирует значения:
CString BetterConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR lpsz = NULL;
pI->GetFileName(&lpsz);
LPTSTR lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
return lpszT; // CString makes copy
}
Макросы просты в использовании и легко для вставки в код, но по мере того, как можно указать из предостережений выше, необходимо соблюдать осторожность при использовании них.