【问题标题】:C++ CLI structure to byte arrayC++ CLI 结构到字节数组
【发布时间】:2010-09-24 17:00:27
【问题描述】:

我有一个表示有线格式数据包的结构。在这个结构中是其他结构的数组。对于大多数情况,我有通用代码可以很好地处理这个问题,但是这个结构数组的情况正在将编组器抛出一个循环。

不安全的代码是不行的,因为我无法获得指向带有数组的结构的指针(啊!)。

我可以从 this codeproject article 看到,有一种非常好的通用方法涉及 C++/CLI,类似于...

public ref class Reader abstract sealed
    {
    public:
        generic <typename T> where T : value class
        static T Read(array<System::Byte>^ data)
        {
            T value;

            pin_ptr<System::Byte> src = &data[0];
            pin_ptr<T> dst = &value;

            memcpy((void*)dst, (void*)src,
                /*System::Runtime::InteropServices::Marshal::SizeOf(T::typeid)*/
                sizeof(T));

            return value;
        }
    };

现在,如果只有结构 -> 字节数组/写入器版本,我将被设置!提前致谢!

【问题讨论】:

    标签: c# struct c++-cli marshalling


    【解决方案1】:

    如果您不控制结构的字节打包,则使用 memcpy 将字节数组复制到结构是极其危险的。一次编组和解组一个字段的结构更安全。当然你会失去你给出的示例代码的通用特性。

    但要回答您的真正问题(并考虑此伪代码):

    public ref class Writer abstract sealed
        {
        public:
            generic <typename T> where T : value class
            static System::Byte[] Write(T value)
            {
                System::Byte buffer[] = new System::Byte[sizeof(T)]; // this syntax is probably wrong.
                pin_ptr<System::Byte> dst = &buffer[0];
                pin_ptr<T> src = &value;
    
                memcpy((void*)dst, (void*)src,
                    /*System::Runtime::InteropServices::Marshal::SizeOf(T::typeid)*/
                    sizeof(T));
    
                return buffer;
            }
        };
    

    【讨论】:

      【解决方案2】:

      这可能不是正确的方法。允许 CLR 添加填充、重新排序项目并更改其在内存中的存储方式。

      如果你想这样做,一定要添加[System.Runtime.InteropServices.StructLayout] 属性来强制结构的特定内存布局。一般来说,我建议你不要乱用 .NET 类型的内存布局。

      【讨论】:

        【解决方案3】:

        实际上,可以编写不安全的代码来执行此操作。请参阅我关于从磁盘读取结构的帖子:Reading arrays from files in C# without extra copy.

        【讨论】:

          【解决方案4】:

          不改变结构当然是合理的建议。我使用大量的 StructLayout 属性来指定打包、布局和字符编码。一切顺利。

          我的问题是我需要一个高性能且最好是通用的解决方案。性能,因为这是一个服务器应用程序和优雅的通用。如果您查看 codeproject 链接,您会发现 StructureToPtr 和 PtrToStructure 方法的执行速度比简单的不安全指针转换慢 20 倍。这是不安全代码充满胜利的领域之一。 C# 只会让您拥有指向原语的指针(而且它不是通用的 - 无法获得指向通用的指针),这就是 CLI 的原因。

          感谢伪代码的悲伤,我会看看它是否完成了工作并报告。

          【讨论】:

            【解决方案5】:

            我错过了什么吗?为什么不创建一个相同大小的新数组并在循环中分别初始化每个元素?

            除非您只针对一个平台,否则使用字节数据数组非常危险...例如,您的方法不考虑源数组和目标数组之间的不同字节序。

            关于您的问题,我也不太了解的是,为什么在您的班级中有一个数组作为成员会导致问题。如果该类来自 .NET 语言,您应该没有问题,否则,您应该能够在不安全代码中获取指针并通过逐一检查指向的元素(使用不安全代码)并添加来初始化新数组他们给它。

            【讨论】:

              猜你喜欢
              • 2011-06-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-12-09
              相关资源
              最近更新 更多