ISAPI und Unicode / Problem mit Typumwandlung von BSTR nach char* [gelöst]
-
Hi, mein ISAPI-Extension Server soll Unicode-Daten zum Client schicken. Ursprünglich unterstützt die WriteClient-Methode nur das char-Format.
Also versuche ich BSTR in char* umzuwandeln:BSTR bstr = L"Test"; _bstr_t tmp(bstr, FALSE); char* c = static_cast<char*>(tmp);
Der Linker gibt zwei nicht aufgelöste externe Symbole aus:
MasterServer.obj : error LNK2019: unresolved external symbol "void __cdecl _com_issue_error(long)" (?_com_issue_error@@YAXJ@Z) referenced in function "public: __thiscall _bstr_t::_bstr_t(unsigned short *,bool)" (??0_bstr_t@@QAE@PAG_N@Z) MasterServer.obj : error LNK2019: unresolved external symbol "char * __cdecl _com_util::ConvertBSTRToString(unsigned short *)" (?ConvertBSTRToString@_com_util@@YAPADPAG@Z) referenced in function "public: char const * __thiscall _bstr_t::Data_t:: GetString(void)const " (?GetString@Data_t@_bstr_t@@QBEPBDXZ)
Welche Headerfiles muss ich einbinden?
Kann ich Unicode überhaupt verlustlos in ein 8 Bit Format pressen?
Kann eine ISAPI-Extension auch direkt Unicode senden (wäre mir lieber)?Gruß, Thomas
-
Thomas++ schrieb:
Hi, mein ISAPI-Extension Server soll Unicode-Daten zum Client schicken.
Warum willst Du "UNICODE" an den Client schicken. I.d.R. Wird UTF-8 zum Client geschickt (was Deinen Ansprüchen genügen würde)...
-
caste doch nach char*. Nicht umwandeln.
-
Jochen Kalmbach schrieb:
Thomas++ schrieb:
Hi, mein ISAPI-Extension Server soll Unicode-Daten zum Client schicken.
Warum willst Du "UNICODE" an den Client schicken. I.d.R. Wird UTF-8 zum Client geschickt (was Deinen Ansprüchen genügen würde)...
Ja, ich brauche UTF-8. Habe das bisher mit Unicode gleichgesetzt, aber da war ich wohl doch auf dem Holzweg. http://de.wikipedia.org/wiki/UTF-8
Reicht also das Casting von BSTR nach char und der Client erkennt dann selbständig, welche chars er wieder zu einem Unicode-Zeichen zusammensetzen muss?
[edit]
Wenn ichs so probiere:BSTR bstr = L"Test 123 xyz"; char* c = (char*)bstr;
und c an den Client sende, kommt nur das erste character, das "T" an.
[edit No.2]
Ist das Casting falsch, oder warum liefert strlen(c) eine 1, sodas nur das erste Zeichen übertragen wird?
-
strlen ist doch nicht für Unicode Strings geeignet!
-
Der Parameter ist auch kein Unicode-String, sondern ein char*.
Das Problem liegt scheinbar beim Casten. Da wird jedes zweite Byte auf 0x00 gesetzt. Dadurch meint scheinbar auch strlen(c) nach dem ersten Zeichen schon das Terminatorzeichen gefunden zu haben und liefert 1 zurück.
-
So, nachdem auch WideCharToMultiByte() nicht funktionieren wollte, hab ich nochmal intensiv gesucht und gefunden:
char* bstr2char(const BSTR bstr) { int n, i; char *buf; n = SysStringLen(bstr); // length of input buf = (char *) malloc(n+1); for (i = 0; i < n; i++) // wide to narrow { buf[i] = (char) bstr[i];} buf[i] = 0; return buf; }
Jetzt geht's.
Gut's Nächtle
Thomas
-
Thomas++ schrieb:
So, nachdem auch WideCharToMultiByte() nicht funktionieren wollte
Was soll denn daran nicht gehen?
Was Du hier machst, hat mit einer "Umwandlung" gar nichts zu tun! Wenn da "wirkliche" UNICODE Zeichen drin sind (also nicht bloss aus dem ASCII-Bereich), dann kommt beim Vlient nur Mist an.
-
BSTR bstr = L"Test"; sende((char*)bstr, SysStringLen(bstr));
-
so? schrieb:
BSTR bstr = L"Test"; sende((char*)bstr, SysStringLen(bstr));
In dem Fall liefert SysStringLen(bstr) immer 0 zurück.
SysAllocString nicht vergessen:
BSTR bstr = SysAllocString(L"Test"); sende((char*)bstr, SysStringLen(bstr));
Geht aber trotzdem nicht, da beim Casting einfach an jedes character ein 0-Byte angehängt wird. UTF-8 wird damit nicht erzeugt.
@Jochen:
Habs jetzt doch noch mal per WideCharToMultiByte probiert:char* bstr2char(const BSTR bstr) { // get the length of bstr int bstrLength = SysStringLen(bstr); // get the length of the corresponding multibyte array unsigned long multiByteLength = WideCharToMultiByte(CP_ACP, NULL, bstr, bstrLength, NULL, 0, NULL, NULL); // allocate a multibyte buffer char* charBuffer = (char *) malloc(multiByteLength + 1); // convert bstr to multibyte WideCharToMultiByte(CP_ACP, NULL, bstr, bstrLength, charBuffer, multiByteLength, NULL, NULL); // append a terminator byte charBuffer[multiByteLength] = 0; return charBuffer; }
Kann man das so stehen lassen?
Gruß, Thomas
-
IMHO ja...
-
Ok, Danke für die Unterstützung!
Gruß, Thomas
-
Auch wenn ich etwas spät dran bin, das kann man so auf keinen Fall stehen lassen. Der Reihe nach:
1.) UNICODE ist ein System, das es erlaubt, jedem Zeichen in jedem Alphabet einen eindeutigen Codepoint zuzuweisen.
2.) Es gibt unterschiedliche Möglichkeiten einem (abstrakten) Codepoint eine Folge von (physikalischen) Bytes zuzuweisen. Die jeweilige Transformation wird durch das Unicode Transformation Format festgelegt. Die beiden häufigsten Transformationen sind UTF-8 und UTF-16.
3.) BSTR's repräsentieren UNICODE Strings und benutzen UTF-16.Mit diesen Informationen lässt sich die ursprüngliche Frage präzisieren: "Wie wandle ich einen String im UTF-16-Format in einen String im UTF-8-Format um?". Die Antwort ist (wie bereits erwähnt) WideCharToMultiByte. Der zuletzt gepostete Code ist allerdings nicht korrekt: Er wandelt UNICODE in ein proprietäres Format um. Der richtige Wert für den
CodePage
Parameter istCP_UTF8
..f