Ошибка компилятора Unicode в простой функции - PullRequest
1 голос
/ 19 июня 2011

Вздох

Я работаю с Microsoft Visual Express C ++ IDE.Я недавно перешел с DevC ++ на эту IDE.

У меня есть функция, которая отлично работает в DevC ++, но в MSVC ++ она не будет компилироваться из-за Unicode (я думаю?).Что мне нужно изменить, чтобы заставить мою функцию компилироваться?

См. Закомментированную строку кода для ошибки компилятора, которую я получаю

map <string, string> GetEvironmentVariablesEx()
{
   map <string, string> envVariables;
   char* environVar = GetEnvironmentStrings();  // Compile error: error C2440: 'initializing' : cannot convert from 'LPWCH' to 'char *'
   char* pos        = strchr( environVar, '\0' );

   // Skip over the "=::=::\0" of the environVar string
   if ( pos != NULL ) { environVar = ++pos; pos = strchr( environVar, '\0' ); }
   else return envVariables;

   while ( true )
   {
       char* delim    = strchr( environVar, '=' );
       if ( delim == NULL )
            break;

       string variable = string( environVar, strlen(environVar)-strlen(delim) );
       string value    = string( ++delim );

       envVariables.insert( pair<string, string>(variable, value) );
       environVar = ++pos;

       // find the "\0\0" that identifies the end of environVar
       if ( pos != NULL && *pos == 0 ) { break; }

       pos = strchr( environVar, '\0' );
   }

   FreeEnvironmentStrings( environVar ); 
   return envVariables;       
}

PS: поскольку это приложение компилируетсяUnicode, означает ли это, что он будет работать как на компьютерах ANSII, так и на компьютерах UNICODE - так что мое приложение сможет работать на международном уровне?

Ответы [ 4 ]

3 голосов
/ 19 июня 2011

Visual C ++ пытается скомпилировать вашу программу с поддержкой Unicode. Под капотом это делается с помощью макросов #define -ing UNICODE и _UNICODE. Это, в свою очередь, заставляет вашу программу использовать Unicode-варианты функций Win32.

Каждая функция Win32 (которая принимает или возвращает строку) имеет два варианта. Например, GetEnvironmentStrings на самом деле две функции: GetEnvironmentStringsA и GetEnvironmentStringsW. GetEnvironmentStrings разрешается к одному из них в зависимости от того, определен ли макрос UNICODE.

Итак, ваша программа компилируется для Unicode, и компилятор не может понять, как взять результат (Unicode) GetEnvironmentStringsW (который является LPWCH - фактически WCHAR *) и поместить его в (ANSI) std::string.

Вы можете сделать одно (или комбинацию) из следующего:

  1. Конвертируйте всю программу в Unicode (начните использовать std::wstring).
  2. Используйте GetEnvironmentStringsA явно.
  3. Перекомпилируйте для не-Unicode вместо.
  4. Воспользуйтесь поддержкой TCHAR в Windows. Вам нужно определить tstring тип .

Это не исчерпывающий список.

Re:

Поскольку это приложение скомпилировано в Unicode, означает ли это, что оно будет работать как на компьютерах ANSII, так и на компьютерах UNICODE - поэтому мое приложение сможет работать на международном уровне?

Компьютеры не являются ANSI или Unicode. Операционные системы есть. Последней версией Windows, которая не поддерживала Unicode, была Windows 3.11 для рабочих групп.

Тем не менее, простая компиляция для Unicode не позволяет вашему приложению работать на международном уровне. Это будет хорошо работать, но Unicode охватывает только наборы символов. Вам по-прежнему нужно беспокоиться о переводе, форматах даты и времени, форматах чисел, различных календарях. Интернационализация, локализация и глобализация - это гораздо больше, чем просто поддержка Unicode.

2 голосов
/ 19 июня 2011

Вы компилируете приложение, предназначенное для строк Unicode, но объявляете строковые переменные ANSI. Если вам нужен Unicode, вам нужно использовать широкие символы, wstring и соответствующие процедуры обработки строк в стандартной библиотеке.

Если вы еще не готовы принять это изменение, измените параметры проекта с Unicode на MBCS, что является слегка противоречащим интуитивно понятным способом получения сборки ANSI.

2 голосов
/ 19 июня 2011

ваш проект представляет собой сборку UNICODE, и вы используете строки ANSI, первым делом замените переменные char на TCHAR и попробуйте снова.

И, как метко предложил @David Heffernan, вам придется переключиться на wstring и точно изменить библиотечные функции из стандартной библиотеки, которую вы используете.

0 голосов
/ 19 июня 2011

Это не так, если ваша программа будет работать правильно на разных компьютерах с Windows или нет - речь идет о преобразованиях, сделанных Windows. Windows API, который принимает в качестве аргумента одну или несколько string , будет иметь две версии: ANSI и Unicode. Хотя не все функции имеют 2 варианта (например, ReadDirectoryChangesW, который доступен только для Unicode).

Когда вы вызываете версию ANSI, Windows необходимо скопировать эту строку ANSI в строку Unicode. Да, это требует выделения памяти, преобразования 1-байтовых символов ANSI в 2-байтовые символы Юникода. И если эта функция выдает одну или несколько строк в виде output , необходимо преобразовать Unicode в ANSI.

Это, очевидно, будет занимать много времени и памяти и замедлять работу вашей программы. Более того, многие из версий ANSI могут / могут изменять переданную строку ANSI, и для передачи строковых констант потребуется , а не . Если вы передадите строковые константы (например, жестко запрограммированный путь к исполняемому файлу CreateProcessA ), это приведет к некоторому исключению памяти Win32.

Поэтому лучше конвертировать все проекты ANSI в Unicode.

PS: разочаровывает использование _T, _TEXT или даже L для строк. Почему компилятор VC ++ не поддерживает опцию для обработки всех "строк" как L "строк" ? : [

...