MarshalAs的使用

作用:

MarshalAs屬性指示如何在託管代碼和非託管代碼之間封送數據。

使用方法:

[MarshalAs(UnmanagedType unmanagedType, 命名參數)]

實際上相當於構造一個MarshalAsAttribute類的對象

常用的UnmanagedType枚舉值:(詳細內容查MSDN)

BStr   長度前綴爲雙字節的 Unicode 字符串;

LPStr  單字節、空終止的 ANSI 字符串。;

LPWStr  一個 2 字節、空終止的 Unicode 字符串;

ByValArray 用於在結構中出現的內聯定長字符數組,應始終使用MarshalAsAttribute的SizeConst字段來指示數組的大小。

注意:

在用Marshal.SizeOf(),即獲取對象的非託管大小時,獲得的是自己定義的大小;

但在實際處理的時候,是按照實際的大小來獲取的

示例:

定義一個固定大小的結構體,代碼如下:

結構的聲明:

[csharp] view plain copy
  1. struct Info  
  2. {  
  3.     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]  
  4.     public char[] name;  
  5.     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]  
  6.     public char[] cipher;  
  7.     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]  
  8.     public char[] signature;  
  9. }  
結構的使用:

[csharp] view plain copy
  1. Info myInfo;  
  2. myInfo.name = name.ToCharArray();  
  3. myInfo.cipher = cipher.ToCharArray();  
  4. myInfo.signature = signature.ToCharArray();  
注意:

[csharp] view plain copy
  1. int size = Marshal.SizeOf(myInfo);  
size=16+16+256

可見,獲取到的非託管大小爲288

但是,查看myInfo對象可以看到其實際大小如下所示:


問題:

這種實際大小和固定大小的不一致性,導致了在用Marshal類進行託管對象和非託管對象的轉換時,會有如下錯誤提示:“未能封送類型,因爲嵌入數組實例的長度與佈局中聲明的長度不匹配。”

解決辦法還沒想到......

小結:
MarshalAs這個屬性很難用,很容易用錯,用好需要對C#、C++和COM數據的佈局方式有一定的瞭解才能做。所以做好使用一些工具來幫你,可以參照我下面的文章:
http://blog.csdn.net/Donjuan/archive/2009/02/05/3865026.aspx
如果你只是感興趣的話,那就忘了這個屬性吧,在.NET 4.0以後,微軟會盡量解決掉這個屬性。

發佈了17 篇原創文章 · 獲贊 9 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章