• wchar_t 宽字符集 研究 和COM的 BSTR VARIANT


    wchar_t 是和 char 平等的地位,即 wchar_t 并非 typedef出来的,是原生的变量。

    简单的说,它拥有两个字节,和short 占用空间一样。

    比如:

    字符串 "我们\n"

    ANSI 的十六进制为:ce d2 c3 c7 0A 00

    6个字节,其中包括字符串最后的\0

    Unicode十六进制为:11 62 EC 4E 0A 00 00 00

    8个字节,所有的字符 全部是2个字节,即使字母  数字 都是,当然换行\n  也是0A 00 了。

    一般 程序中字符串 前面加个  L"" 就表示 是Unicode 字符串了。

    windows下有一个 宏 _T("") 和上面的一样。

    1.第一个简单的问题,如何打印出来 Unicode?

    2个字节,可以按照 数字打印,但是如果要按照字符 打印,用普通的printf 是不行了。

    可以使用wprintf打印,也就是 普通的 printf前面加一个 Wide的 W。类似的函数都是,比如 wsprintf。

        char* lpszText = "我们\r\n";//ANSI:ce d2 c3 c7
                                //Unicode:11 62 EC 4E
                                //回车 \r 0D  \n 0A
        printf("char * text: %s 0x%08x 0x%08x \nANSI编码是   :", lpszText, lpszText, *lpszText );
        print_hex_to_file(stdout,(const uint8_t *)lpszText,strlen(lpszText)+1,16);//此函数自己编写的
    
        BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText);
        wprintf(L"BSTR text: %s 0x%08x 0x%08x \nUniCode编码是:", bstrText, bstrText, *bstrText);
        print_hex_to_file(stdout,(const uint8_t *)bstrText,wcslen(bstrText)*2+2,16);

    的结果为:

    char * text: 我们 
    0x013fbd80 0xffffffce ANSI编码是 :0x ce d2 c3 c7 0d 0a 00 BSTR text: 我们
    0x007be5b4 0x00006211 UniCode编码是:0x 11 62 ec 4e 0d 00 0a 00 00 00

    对了,开始我用wprintf始终无法打印中文,后来 添加了下面的两句 才可以了。

        #include <locale.h>
    
        setlocale( LC_CTYPE, "chs" );

    源码的编码 是 ANSI 或  UniCode 对结果 都没有什么影响。

    对了 如果要打印单个 wchar_t 怎么打印呢?上面都是指针,都是字符串,那好好办。单个。。。

        setlocale( LC_CTYPE, "chs" );
        WCHAR wstr1;
        wchar_t wstr2;
        wstr1=L'';
        wstr2=L'';
        wprintf(L"我们 在宽字符集(%c,%c) 的每个大小为:%d 字节\n",wstr1,wstr2,sizeof(wstr1));

    赋值的时候 始终记住 L  ,结果正常。

    我们 在宽字符集(我,们) 的每个大小为:2 字节

    如果你将 '我' 赋值给 一个 char 类型,那么 你只能得到 '我' ce d2  的 前一个 字节。打印出来 肯定 就是乱码  ? 了。

    char ss;
    ss='';
    printf("ss=%c\n",ss);
    
    
    
    结果是:
    ss=? 

    并且 ?  后面是没有换行的,因为 \n 已经和 %c 融合 为 ?  了。。反正 ce 打印出来 或许 很诡异的。

    2.第二个简单的问题,如何 与 char 类型 互相转换

    int ConvertStringToBSTRDemo()
    {
        char* lpszText = "Test";
        printf("char * text: %s\n", lpszText);
        BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText);
        wprintf(L"BSTR text: %s\n", bstrText);
        ::SysFreeString(bstrText);
    
        return 0;
    };
    int ConvertBSTRToStringDemo()
    {
        BSTR bstrText = ::SysAllocString(L"Test");
        wprintf(L"BSTR text: %s\n", bstrText);
        char* lpszText2 = _com_util::ConvertBSTRToString(bstrText);
        printf("char * text: %s\n", lpszText2);
        ::SysFreeString(bstrText);
        delete[] lpszText2;
    
        return 0;
    };

    这个全局函数 SysFreeString() 发现 不加 貌似 也没有内存泄漏?(VLD检测)

    我靠,我知道了,可能是VLD没有重载COM里的内存分配释放,所以 还是 去掉 SysFreeString前的注释。

    经过实验 循环10 000 000次,会发生 300MB左右的内存泄漏。但是VLD确实无法检测。所以 千万得小心了!

    COM编程里的 BSTR其实就是wchar_t* 类型,有BSTR的地方就是分配了指针的,一定要自己释放内存的!

    BSTR和String(char *) 的转换,其实就是 wchar_t* 和 char * 的转换了。这是COM的方法

    还可以使用stdlib里的方法:

     wcstombs 和 mbstowcs  wcs应该就是WideCString ,但是 mbs 怎么就表示 ansi普通的字符编码 我就不知道缩写了

        wchar_t   ws[10]; //sizeof(ws)=20字节
        wsprintf(ws,L"我们");
        char cs[50];
        sprintf(cs,"");
        //清除数据 与初始化
        //wchar_t * 转化为 char *
        int ret=0;
        printf("wcstombs前:       cs=%4s ws=%%S=%S\n",cs,ws);
        ret=wcstombs(cs,ws,sizeof(ws));
        printf("wcstombs后: ret=%d,cs=%4s ws=%%S=%S\n",ret,cs,ws);
    
        wsprintf(ws,L"");
        //清除数据 与初始化
        //char * 转化为 wchar_t *
        wprintf(L"mbstowcs前:       ws=%4s cs=%%S=%S\n",ws,(cs));
        ret=mbstowcs(ws,cs,sizeof(ws)*2);
        wprintf(L"mbstowcs后: ret=%d,ws=%2s cs=%%S=%S\n",ret,ws,(cs));

    运行结果

    wcstombs前:       cs=     ws=%S=我们
    wcstombs后: ret=4,cs=我们 ws=%S=我们
    mbstowcs前:       ws=     cs=%S=我们
    mbstowcs后: ret=2,ws=我们 cs=%S=我们

    windows下也有另外的相同意思的API

     //MultiByteToWideChar 

    最后 加上 我喜欢的 print_hex_to_file函数

    void print_hex_to_file(FILE*fp,const uint8_t *array, int count/*aray的大小*/,int lineCount/*默认应该是16*/)
    {
        int i;
        fprintf(fp,"0x ");
        for(i = 0; i < count; ){
            fprintf(fp,"%02x ", array[i]);
            i++;
            if ( !(i % lineCount) && i<count){
                fprintf (fp,"\n0x ");
            }
        }
        fprintf(fp,"\n");
    };
  • 相关阅读:
    [转载]「服务」WCF中NetNamedPipeBinding的应用实例
    [转载] ABP框架理论学习之后台工作(Jobs)和后台工作者(Workers)
    .NET Core use NLog
    把.netcore console 安装到Windows 系统服务。
    利用Linq Skip() Take()分页
    C#访问Java的WebService添加SOAPHeader验证的问题
    马丁福勒 关于微服务特点的描述
    转载 springboot 配置读取
    luajit与NYI
    lua启用lua-resty-core
  • 原文地址:https://www.cnblogs.com/ayanmw/p/2672743.html
Copyright © 2020-2023  润新知