zoukankan      html  css  js  c++  java
  • P/Invoke继续谈

    上回说到封装rocketmq-client-cpp的时候会碰到内存损坏的问题,本以为能收到服务端的消息就万事大吉了,但是在深入测试的过程中,发现收到的消息会有乱码出现,

    之前和服务端的研发人员讨论过字符集的问题,知道服务器回传的是UTF8的字符串,所以在接收时用下面这样的方式可以在大部分情况下得到正确的内容:

    return Encoding.UTF8.GetString(Encoding.Default.GetBytes(Marshal.PtrToStringAnsi(GetMessageIdNative(message))));

    但是在少数情况下会有乱码内容,比较之后发现是中英文符号混杂的情况就会出现这种问题,经过反复测试和思考之后确认需要的是Marshal.PtrToStringUTF8,

    可惜目前的项目都是在.NET Framework下开发,PtrToStringUTF8在.NET Framework中完全没有支持,所以只能自己写一个了

    static string PtrToStringUTF8(IntPtr ptr)
    {
        var bytesCount = 0;
        byte b;
        do
        {
            b = Marshal.ReadByte(ptr, bytesCount);
            bytesCount++;
        }
        while (b != 0);
        var bytes = new byte[bytesCount - 1];
        Marshal.Copy(ptr, bytes, 0, bytesCount - 1);
        return Encoding.UTF8.GetString(bytes);
    }

    没过几天,又遇到个接入某省定制多功能读卡器的需求,在这里碰到了一个看起来很简单的函数,声明如下:

    long iReadXXX(char* pOutInfo)

    这里的pOutInfo是一个长度为4096的输出参数,所以虽然也是要接收一个字符串,但是通过输出参数的形式,而不是上次的返回值,平台调用的形式也就必然不同。

    这里采用的是接收字符数组的方式来进行调用,声明如下:

    public static extern int iReadXXX(IntPtr pOutInfo);

    调用代码如下:

    byte[] bytes = new byte[4096];
    GCHandle pinned = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    var result = iReadXXX(pinned.AddrOfPinnedObject());
    pinned.Free();
    int count = bytes.ToList().FindIndex(b => b == 0);
    var text = Encoding.Default.GetString(bytes, 0, count);
  • 相关阅读:
    精妙Sql语句
    TSQL是否有循环语句?类似C语言的for?如何查看有哪些用户连接到服务器上?如何强制其退出?
    Tools1.4
    Set Up1.2
    Getting Started1.0
    Start Developing iOS Apps Today1.1
    Language1.5
    Jump Right In1.3
    编译器错误信息: CS0246: 找不到类型或命名空间名称“Discuz”(是否缺少 using 指令或程序集引用?)
    ashx文件无法访问
  • 原文地址:https://www.cnblogs.com/s5689412/p/12773177.html
Copyright © 2011-2022 走看看