4

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

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

我可以从这篇 codeproject 文章中看到,有一种非常好的通用方法,涉及 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;
        }
    };

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

4

5 回答 5

2

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

如果要执行此操作,请务必添加[System.Runtime.InteropServices.StructLayout]属性以强制结构的特定内存布局。一般来说,我建议你不要弄乱 .NET 类型的内存布局。

于 2008-12-01T07:19:00.713 回答
2

如果您不控制结构的字节打包,则使用 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;
        }
    };
于 2008-12-01T05:16:31.227 回答
1

Unsafe code can be made to do this, actually. See my post on reading structs from disk: Reading arrays from files in C# without extra copy.

于 2009-02-14T19:06:27.613 回答
0

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

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

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

于 2009-02-03T13:57:44.007 回答
0

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

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

感谢您的psuedocode悲伤,我会看看它是否能完成工作并报告。

于 2008-12-01T21:14:10.277 回答