2008-12-01 86 views
3

我有一個表示有線格式數據包的結構。在這個結構中是其他結構的數組。我有泛型代碼,在大多數情況下可以很好地處理這個問題,但是這個結構體的數組正在拋出循環的編組器。C++ CLI結構到字節數組

不安全的代碼是一個不行,因爲我不能得到一個指向具有數組結構的指針(argh!)。

我可以從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; 
     } 
    }; 

現在,如果只是有結構 - >字節數組/寫器版本我將被設置!提前致謝!

+0

@JasonCoder - 它的工作? – Toybuilder 2009-01-29 19:18:06

回答

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

這可能是不正確的方式去。 CLR允許添加填充,重新排序項目並改變它存儲在內存中的方式。

如果你想這樣做,一定要添加[System.Runtime.InteropServices.StructLayout]屬性來強制結構的特定內存佈局。一般來說,我建議你不要混淆.NET類型的內存佈局。

0

不改變結構肯定是合理的建議。我使用大量的StructLayout屬性來指定打包,佈局和字符編碼。一切都很順利。

我的問題是,我需要一個性能,最好是通用的解決方案。性能,因爲這是一個服務器應用程序和通用的優雅。如果您查看codeproject鏈接,您會看到StructureToPtr和PtrToStructure方法的執行速度比簡單的不安全指針強制轉換慢20倍。這是不安全代碼充滿勝利的領域之一。 C#只會讓你指向原語(並且它不是泛型的 - 不能得到指向泛型的指針),所以這就是CLI的原因。

感謝psuedocode悲傷,我會看看它是否完成了工作並報告回來。

0

我錯過了什麼嗎?爲什麼不創建一個相同大小的新數組並在循環中分別初始化每個元素?

使用字節數組數據是相當危險的,除非你是靶向只有一個平臺......例如你的方法沒有考慮到源和目標陣列之間不同的字節順序。

東西我真的不明白你的問題,以及因此具有如類的成員是造成問題的一個陣列。如果該類來自.NET語言,則不應該有任何問題,否則,應該能夠將指針放入不安全的代碼中,並通過逐個指出要素(使用不安全的代碼)並添加一個新數組來初始化一個新數組他們對它。