如何使Tcl_WriteChars支持Unicode?

如何使Tcl_WriteChars支持Unicode?,unicode,utf-8,tcl,Unicode,Utf 8,Tcl,是否需要进行任何初始设置才能正确输出UTF-8字符?e、 g #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(ch

是否需要进行任何初始设置才能正确输出UTF-8字符?e、 g

#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;
}

您需要将编码配置为UTF-8(并且您正在运行的主机似乎在使用其他默认值)。在向频道写入之前执行此操作

Tcl_SetChannelOption(interp,channel,“-encoding”,“utf-8”);
正确地说,您应该检查它的返回码(如下所示),但所有通道都有该选项,并且
utf-8
编码直接烘焙到Tcl中,因此不会失败

if(Tcl\u设置通道选项(interp,通道,“-encoding”,“utf-8”)!=Tcl\u确定){
返回TCL_错误;
}

[编辑]:重新仔细阅读代码后(首先发现系统的默认编码实际上是UTF-8),实际问题是您没有调用
Tcl\u FindExecutable()
。这个例程有点命名错误,因为它实际上(除了使
info-nameofexecutable
在脚本中工作之外)是让Tcl初始化它的内部库。特别是,它初始化了编码管理子系统,这就是它确定系统编码真正是什么的点(否则它会退回到
iso8859-1
,这是需要恢复的问题最少的普通编码)

您的代码应为:

#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;
}
#包括

int main(int argc,char*argv[])///谢谢!它起作用了。我已经在我的主机中使用
Tcl\u GetChannelOption
进行了检查,它返回
iso8859-1
。真奇怪,因为我已经将主机区域设置为UTF-8.Oh!我才意识到问题出在哪里!您从未调用Tcl_FindExecutable
;这很重要,因为这就是计算系统编码实际是什么的方法。我还注意到
tclsh
没有这个问题,因为它将在
Tcl\u MainEx
中调用
tclpseetilencodings
(它也依赖于
Tcl\u FindExecutable
)。顺便说一句,我很好奇为什么在
TclInitEncodingSubsystem
中没有调用
TclpSetInitialEncodings
?这似乎是一个更合适的地方。该函数将由
tclinitsubsystem
调用,该函数由
Tcl\u FindExecutable
Tcl\u CreateInterp
调用。由于我正在将Tcl嵌入另一个系统,并且
argv0
未暴露于其扩展系统,因此无法调用
Tcl\u FindExecutable
。您可以传递
NULL
而不是
argv[0]
。这意味着
info nameofexecutable
可能是错误的(取决于平台的内部猜测试探法有多好),但它确实正确初始化了编码和标准通道。(它们是分开的,因为存在一个邪恶的排序依赖项IIRC。)
#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;
}