Zeichencodierung
-
Hallo zusammen,
ich bin auf der Suche nach Hilfestellungen zum Beginnen bei folgendem Problem:
Ich habe ein Java-Programm, von dem ich per JNI meine C(++) Bilbiothek einbinde. In meiner C++ Bibliothek greife ich auf eine weitere externe Bibliothek zu.
Nun brauche ich bei vielen Funktionen Strings. Sprich ich habe einen Java-String, der ja per Standardbibliothek recht einfach in andere Encodierungen konvertiert werden kann. Und die externe C(++)-Bibliothek erwartet (const) char* im ISO8859-15 Zeichensatz.
Okay dachte ich mir: Unter Windows (MSVC2013) angefangen, der Typ jchar ist zufällig genauso groß wie wchar_t (2Byte), also per std::memcpy den Spass kopiert und in einen std::wstring gestopft. Und danach per std::wcstombs in einen std::string konvertiert mit dem ich dann weiterarbeiten konnte.
Hat soweit halbwegs geklappt.Pseudocode
class C { private static native void cfoo(String s); public void jfoo() { cfoo("123abcäöü"); } }std::string convertWithWcsToMbs(std::wstring const& wstr) { if ( wstr.size() == 0 ) return std::string(); std::string dest( 2 * wstr.size(), 0 ); std::size_t length = 0; auto result = wcstombs_s( &length, &dest[ 0 ], dest.size(), wstr.c_str(), _TRUNCATE ); assert( result == 0 ); dest.resize( length ); while ( dest.back() == 0 ) dest.pop_back(); return dest; } JNIEXPORT void JNICALL JAVA_C_cfoo(JNIEnv * env, jclass, jstring jstr) { const jchar* str1 = env->GetStringChars(jstr, nullptr); const wchar_t* str2 = reinterpret_cast<const wchar_t*>(str1); std::wstring str3 = str2; std::string s = convertWithWcsToMbs(str3); callExternalLib(s.c_str()); }Soweit so gut (oder auch nicht). Allein durch die Funktion wcstombs ist das ganze schon nur für Windows gedacht (MSVC zeigt die std::wcstombs-Funktion als deprecated und unsicher an).
Als ich dann allein die Umwandlung von jchar* nach wchar_t* auf meiner Linux Kiste vollziehen wollte, hab ich gemerkt "Oh shit wchar_t ist ja gar nicht in seienr Größe einheitlich definiert", denn unter dem Linux-GCC ist wchar_t 4 Byte groß, statt 2.
Naja Short Story Long, ich hab bisher mich noch nie mit C++-Zeichencodierungen auseinander gesetzt (selbst in Java nur weniger als rudimentär), ich hatte immer nur im Kopf, dass es da nicht ganz trivial war.
Wie gehe ich an das Problem dran? Wodrauf muss ich achten?
Ich hab gesehen es gibt im Standard sowas wie codecvt_utf8, codecvt_utf16 und codecvt_utf8_utf16. Aber was ist das, was kann es und wie kann?
Shit, sorry Jungs, aber mir raucht da etwas der Kopf.
lg mosho
Rest in Ruhestand: Marc++us

-
Als erstes willst du std::u16string und nicht std::wstring verwenden.
Probier mal
const jchar* str1 = env->GetStringChars(jstr, nullptr); static_assert(sizeof(jchar)==sizeof(char16_t),""); const char16_t *str2 = reinterpret_cast<const char16_t*>(str1); std::u16string s(str2, str+len); std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert; std::string s = convert.to_bytes(s); callExternalLib(s.c_str());
-
Mh, nein so bei den Versuchen kam auch nix raus.
"öäü"(const jchar*) -> 3 Zahlen im Bereich von 200irgendwas(std::u16string) -> 6 extrem komische Zeichen (std::string)
-
Skym0sh0 schrieb:
Mh, nein so bei den Versuchen kam auch nix raus.
"öäü"(const jchar*) -> 3 Zahlen im Bereich von 200irgendwas(std::u16string) -> 6 extrem komische Zeichen (std::string)
Ja, ist schon richtig.
Du hast jetzt UTF-8, da besteht ein Zeichen aus mehreren.
Das musst du dann zu deiner Codepage kriegen.
-
Hä? Was da dann heisst?
Bzw. wie mach ich das?
Ich fühl mich grad echt richtig richtig dumm ...

-
Kann es sein, dass der GCC 4.8.2 unter Ubuntu den codecvt-Spass noch nicht kann?!
-
Also du hast einen String in welchem Encoding?
Und in was willst du es kriegen?
-
Laut JNI-Reference entweder in UTF-8 oder in Unicode Codierung.
Brauchen tue ich (für die Nutzung der externen Bibliothek) das ISO-8859-15 Format. Halt die deutsche Sprache inklusive Euro zeichen.
Ich brauchs unter Windows (MSVC 2013 mit Update) und Linux (Eclipse&GCC 4.8.2). Am liebsten plattformneutral, aber mittlerweile ists auch egal, wenn ich bei Anpassungen halt zweimal Code anfassen muss. (Bin langsam leicht verzweifelt und weiss nicht mehr wo mir der Kopf steht.)
Am liebsten ohne externe Bibiliotheken, wobei sowas wie utf8cpp ganz gut einbindbar ist.
-
Nachtrag, unter Windows der Weg über std::wstring und dann std::wcstombs klappt dankd es Euro-Zeichens auch nicht (mehr)...