2012-06-28 13 views
8

Attualmente sto lavorando a un progetto di hobby (C/C++) che dovrebbe funzionare su Windows e Linux, con supporto completo per Unicode. Purtroppo, Windows e Linux utilizzano codifiche diverse che rendono le nostre vite più difficili.Unicode multipiattaforma in C/C++: quale codifica usare?

Nel mio codice sto provando a utilizzare i dati nel modo più universale possibile, semplificando sia Windows che Linux. In Windows, wchar_t è codificato come UTF-16 di default e come UCS-4 in Linux (correggimi se ho torto).

Il software si apre ({_wfopen, UTF-16, Windows}, {fopen, UTF-8, Linux}) e scrive i dati nei file in UTF-8. Finora è tutto fattibile. Fino a quando non ho deciso di utilizzare SQLite.

L'interfaccia C/C++ di SQLite consente stringhe codificate a uno o due byte (click). Ovviamente questo non funziona con wchar_t in Linux, dato che il wchar_t in Linux è di 4 byte per impostazione predefinita. Pertanto, scrivere e leggere da sqlite richiede la conversione per Linux.

Attualmente il codice è ingombrante con eccezioni per Windows/Linux. Speravo di aderire all'idea livello di memorizzazione dei dati in wchar_t:

  • wchar_t in Windows: Percorsi su senza un problema, la lettura/scrittura su SQLite senza un problema. Scrivere i dati su un file dovrebbe essere fatto comunque in UTF-8.
  • wchar_t in Linux: eccezione per i percorsi di file dovuti alla codifica UTF-8, conversione prima della lettura/scrittura in sqlite (wchar_t), e lo stesso per Windows quando si scrivono dati in un file.

Dopo aver letto (here) ero convinto che avrei dovuto attenermi a wchar_t in Windows. Ma dopo aver ottenuto tutto questo, il problema è iniziato con il porting su Linux.

Attualmente sto pensando di ripetere tutto per attaccare con semplice char (UTF-8) perché funziona con Windows e Linux, tenendo presente che ho bisogno di 'WideCharToMultiByte' ogni stringa in Windows per raggiungere UTF-8. L'utilizzo di semplici stringhe basate su char riduce notevolmente il numero di eccezioni per Linux/Windows.

Hai qualche esperienza con unicode per multipiattaforma? Qualche idea sull'idea di memorizzare semplicemente i dati in UTF-8 invece di usare wchar_t?

+0

La codifica dei caratteri a 2 byte è decisamente * non * UTF-16.UTF-16 è da 2 a 4 byte e UTF-8 è da 1 a 4 byte. Windows 'wchar_t' non è UTF-16, è UCS2. In pratica potresti non notare la differenza perché UCS2 copre il BMP, ma se mai i tuoi utenti decidono che devono avere dati in Ogham o rune ... – user268396

+1

Windows usa UTF-16, e usa 'wchar_t' per contenere UTF-16 dati, e lo ha fatto da Windows 2000. –

+3

Su quanto sia utile wchar_t e per cosa: http://stackoverflow.com/a/11107667/365496 – bames53

risposta

6

UTF-8 su tutte le piattaforme, con la conversione just-in-time in UTF-16 per Windows è una tattica comune per Unicode multipiattaforma.

+0

Regolerei leggermente quell'istruzione e dico: codifica nativa su tutte le piattaforme, con conversione just-in-time in/da UTF-8. È necessaria la conversione just-in-time, ogni volta che le stringhe di caratteri lasciano l'applicazione (ad esempio, scrivendo su un file, inviando dati su un socket di rete, passando l'input a una libreria, ecc.). Certo, tutto dipende dallo scenario specifico. – IInspectable

2

Il nostro software è anche multipiattaforma e abbiamo riscontrato problemi simili. Abbiamo deciso che il nostro obiettivo è avere la minima quantità di conversioni possibile. Ciò significa che utilizziamo wchar_t su Windows e char su Unix/Mac.

Facciamo questo sostenendo _T e LPCTSTR e simili Unix e avendo funzioni generiche che convertire facilmente tra std::string e std::wstring. Abbiamo anche un std::basic_string<TCHAR> (tstring) generico che usiamo nella maggior parte dei casi.

Finora funziona abbastanza bene. Fondamentalmente la maggior parte delle funzioni prende uno tstring o uno LPCTSTR e quelli che non avranno i loro parametri convertiti da un tstring. Ciò significa che la maggior parte delle volte non convertiamo le nostre stringhe e passiamo attraverso la maggior parte dei parametri.

+2

Anche questa è una soluzione possibile, ma ancora un po 'hacky. Inoltre, dalla mia lettura ho appreso che dovrei evitare di usare TCHAR in quanto è stato introdotto per supportare la retrocompatibilità con i vecchi software passando a MBCS invece che al flag Unicode. – ErikKou

+0

@Fozi, come supporto _T su Ubuntu Linux? Grazie mille. – Frank

+0

@ErikKou, Qual è la tua possibile soluzione per l'emulazione della macro di Windows _T in Unix o Linux? Grazie. – Frank