2012-06-28 29 views
8

Actualmente estoy trabajando en un proyecto hobby (C/C++) que se supone que funciona tanto en Windows como en Linux, con soporte completo para Unicode. Tristemente, Windows y Linux usan diferentes codificaciones haciendo nuestras vidas más difíciles.Unicode multiplataforma en C/C++: ¿Qué codificación usar?

En mi código intento utilizar los datos de la forma más universal posible, lo que facilita tanto para Windows como para Linux. En Windows, wchar_t está codificado como UTF-16 por defecto, y como UCS-4 en Linux (corrígeme si estoy equivocado).

Mi software se abre ({_wfopen, UTF-16, Windows}, {fopen, UTF-8, Linux}) y escribe datos en archivos en UTF-8. Hasta ahora todo es factible. Hasta que decidí usar SQLite.

La interfaz C/C++ de SQLite permite cadenas de uno o dos bytes codificadas (click). Por supuesto, esto no funciona con wchar_t en Linux, ya que el wchar_t en Linux tiene 4 bytes por defecto. Por lo tanto, escribir y leer desde sqlite requiere conversión para Linux.

Actualmente el código está abarrotado de excepciones para Windows/Linux. Tenía la esperanza de que se adhieren a la idea estándar de almacenamiento de datos en wchar_t:

  • wchar_t en Windows: Rutas de archivos sin ningún problema, la lectura/escritura a SQLite sin ningún problema. Escribir datos en un archivo se debe hacer en UTF-8 de todos modos.
  • wchar_t en Linux: excepción para los filepaths debido a la codificación UTF-8, conversión antes de leer/escribir en sqlite (wchar_t), y lo mismo para Windows al escribir datos en un archivo.

Después de leer (here) Estaba convencido de que debería quedarme con wchar_t en Windows. Pero después de hacer que todo funcionara, el problema comenzó con la migración a Linux.

Actualmente estoy pensando en volver a hacer todo para seguir con simple char (UTF-8) porque funciona tanto con Windows como con Linux, teniendo en cuenta que necesito 'WideCharToMultiByte' cada cadena en Windows para lograr UTF-8. Usar cadenas simples basadas en char * reducirá en gran medida la cantidad de excepciones para Linux/Windows.

¿Tiene alguna experiencia con Unicode para multiplataforma? ¿Alguna idea sobre la idea de simplemente almacenar datos en UTF-8 en lugar de usar wchar_t?

+0

La codificación de caracteres de 2 bytes definitivamente * no * UTF-16.UTF-16 tiene de 2 a 4 bytes, y UTF-8 tiene de 1 a 4 bytes. Windows 'wchar_t' no es UTF-16, es UCS2. En la práctica, es posible que no note la diferencia porque UCS2 cubre el BMP, pero si alguna vez sus usuarios deciden que deben tener datos en Ogham o runas ... – user268396

+1

Windows SÍ usa UTF-16, y SÍ usa 'wchar_t' para contener UTF-16 datos, y lo ha hecho desde Windows 2000. –

+3

Sobre lo útil que es wchar_t y para qué: http://stackoverflow.com/a/11107667/365496 – bames53

Respuesta

6

UTF-8 en todas las plataformas, con la conversión justo a tiempo en UTF-16 para Windows es una táctica común para Unicode multiplataforma.

+0

Ajusto ligeramente esa afirmación y digo: codificación nativa en todas las plataformas, con conversión justo a tiempo hacia/desde UTF-8. Se requiere conversión justo a tiempo, siempre que las cadenas de caracteres dejen la aplicación (por ejemplo, escribir en un archivo, enviar datos a través de un socket de red, pasar la información a una biblioteca, etc.). Por supuesto, todo depende del escenario específico. – IInspectable

2

Nuestro software es multiplataforma también, y nos enfrentamos a problemas similares. Decidimos que nuestro objetivo es tener la menor cantidad posible de conversiones. Esto significa que usamos wchar_t en Windows y char en Unix/Mac.

Hacemos esto mediante el apoyo _T y LPCTSTR y similares en Unix y por tener funciones genéricas que se convierten fácilmente entre std::string y std::wstring. También tenemos un std::basic_string<TCHAR> genérico (tstring) que usamos en la mayoría de los casos.

Hasta ahora, esto funciona bastante bien. Básicamente, la mayoría de las funciones toman tstring o LPCTSTR y las que no lo hacen obtendrán sus parámetros convertidos de tstring. Eso significa que la mayoría de las veces no convertimos nuestras cadenas y pasamos por la mayoría de los parámetros.

+2

Esta es una posible solución también, pero todavía un poco hacky. Además, según mis lecturas, he aprendido que debería evitar el uso de TCHAR, ya que se introdujo para admitir la compatibilidad con versiones anteriores de software más antiguo al cambiar a MBCS en lugar de a la bandera Unicode. – ErikKou

+0

@Fozi, ¿Cómo apoyo _T en Ubuntu Linux? Muchas gracias. – Frank

+0

@ErikKou, ¿Cuál es su posible solución para emular la macro _T de Windows en Unix o Linux? Gracias. – Frank

Cuestiones relacionadas