2017-10-22 3 views
2

Ist eine Ersteinrichtung erforderlich, um Tcl_WriteChars UTF-8-Zeichen korrekt ausgeben zu lassen? z.B.Wie kann Tcl_WriteChars Unicode unterstützen?

#include <tcl.h> 

int main() 
{ 
     Tcl_Interp *tcl = Tcl_CreateInterp(); 

     Tcl_Channel channel = Tcl_GetStdChannel(TCL_STDOUT); 

     Tcl_WriteChars(channel, "hello\n", -1); 
     Tcl_WriteChars(channel, "你好\n", -1); 
     Tcl_WriteRaw(channel, "你好\n", -1); 

     Tcl_Close(tcl, channel); 

     Tcl_DeleteInterp(tcl); 

     return 0; 
} 

Quellcode wird in UTF-8-Codierung gespeichert und folgende Ausgabe ist von UTF-8 locale Linux:

hello 
?? 
你好 

Antwort

3

Sie müssen die Codierung konfigurieren UTF-8 (und die Gastgeber sein Sie laufen auf scheint etwas anderes für seine Standardeinstellung zu verwenden). Tun Sie dies, bevor Sie in den Kanal schreiben.

Tcl_SetChannelOption(interp, channel, "-encoding", "utf-8"); 

richtig, sollten Sie für den Rückgabecode, dass der Check (wie unten), aber alle Kanäle haben diese Option und die utf-8 Codierung direkt in Tcl gebacken wird, so wird es nicht scheitern.

if (Tcl_SetChannelOption(interp, channel, "-encoding", "utf-8") != TCL_OK) { 
    return TCL_ERROR; 
} 

[EDIT]: der Code ein wenig mehr sorgfältig neu zu lesen Nachdem (und fand heraus, dass das Standard-Kodierung des Systems wirklich UTF-8 in erster Linie ist), das tatsächliche Problem ist, dass du nicht anrufst Tcl_FindExecutable(). Diese Routine ist ein bisschen falsch benannt, denn was sie tatsächlich tut (abgesehen davon, dass sie info nameofexecutable in Skripten arbeiten lässt), lässt Tcl seine interne Bibliothek initialisieren. Insbesondere initialisiert es das Codierungsverwaltungssubsystem, und das ist der Punkt, an dem es herausfindet, was die Systemcodierung wirklich ist (andernfalls fällt es auf iso8859-1 zurück, was die am wenigsten problematische gewöhnliche Codierung ist, von der wiederhergestellt werden soll).

sollte Ihr Code lesen:

#include <tcl.h> 

int main(int argc, char *argv[]) /// <<<< CHANGED HERE 
{ 
    Tcl_FindExecutable(argv[0]); /// <<<< CHANGED HERE 

    Tcl_Interp *tcl = Tcl_CreateInterp(); 

    Tcl_Channel channel = Tcl_GetStdChannel(TCL_STDOUT); 

    Tcl_WriteChars(channel, "hello\n", -1); 
    Tcl_WriteChars(channel, "你好\n", -1); 
    Tcl_WriteRaw(channel, "你好\n", -1); 

    Tcl_Close(tcl, channel); 

    Tcl_DeleteInterp(tcl); 

    return 0; 
} 

Ich gehe davon aus Sie einen Compiler verwenden, die mit dem Setzen Erklärungen nach Aussagen zufrieden ist. Das ist eine weit verbreitete C99-Funktion (und ist auch in C++), also erwarte ich, dass es in Ordnung ist.

+0

Danke! Es klappt. Ich habe mit 'Tcl_GetChannelOption' in meinem Host überprüft, die' iso8859-1' zurückgibt. Wirklich seltsam, da ich mein Host-Gebietsschema auf UTF-8 eingestellt habe. –

+0

Oh! Ich habe gerade erkannt, was das Problem ist! Sie rufen niemals 'Tcl_FindExecutable' auf; Das ist wichtig, denn das ergibt, was die Systemcodierung eigentlich ist. –

+0

Ich habe auch bemerkt, dass 'tclsh' dieses Problem nicht hat, da es' TclpSetInitialEncodings' (auf das sich 'Tcl_FindExecutable' auch stützt) in' Tcl_MainEx' aufruft. BTW, ich bin neugierig, warum 'TclpSetInitialEncodings' nicht in' TclInitEncodingSubsystem' aufgerufen wird? Was scheint ein geeigneterer Ort zu sein. Diese Funktion wird von 'TclInitSubsystems' aufgerufen, welches sowohl von' Tcl_FindExecutable' als auch von 'Tcl_CreateInterp' aufgerufen wird. Da ich Tcl in ein anderes System einbette und 'argv0' nicht seinem Erweiterungssystem ausgesetzt ist, kann' Tcl_FindExecutable' nicht aufgerufen werden. –

Verwandte Themen