作用:
MarshalAs屬性指示如何在託管代碼和非託管代碼之間封送數據。
使用方法:
[MarshalAs(UnmanagedType unmanagedType, 命名參數)]
實際上相當於構造一個MarshalAsAttribute類的對象
常用的UnmanagedType枚舉值:(詳細內容查MSDN)
BStr 長度前綴爲雙字節的 Unicode 字符串;
LPStr 單字節、空終止的 ANSI 字符串。;
LPWStr 一個 2 字節、空終止的 Unicode 字符串;
ByValArray 用於在結構中出現的內聯定長字符數組,應始終使用MarshalAsAttribute的SizeConst字段來指示數組的大小。
注意:
在用Marshal.SizeOf(),即獲取對象的非託管大小時,獲得的是自己定義的大小;
但在實際處理的時候,是按照實際的大小來獲取的
示例:
定義一個固定大小的結構體,代碼如下:
結構的聲明:
- struct Info
- {
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
- public char[] name;
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
- public char[] cipher;
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
- public char[] signature;
- }
- Info myInfo;
- myInfo.name = name.ToCharArray();
- myInfo.cipher = cipher.ToCharArray();
- myInfo.signature = signature.ToCharArray();
- int size = Marshal.SizeOf(myInfo);
可見,獲取到的非託管大小爲288
但是,查看myInfo對象可以看到其實際大小如下所示:
問題:
這種實際大小和固定大小的不一致性,導致了在用Marshal類進行託管對象和非託管對象的轉換時,會有如下錯誤提示:“未能封送類型,因爲嵌入數組實例的長度與佈局中聲明的長度不匹配。”
解決辦法還沒想到......
小結:
MarshalAs這個屬性很難用,很容易用錯,用好需要對C#、C++和COM數據的佈局方式有一定的瞭解才能做。所以做好使用一些工具來幫你,可以參照我下面的文章:
http://blog.csdn.net/Donjuan/archive/2009/02/05/3865026.aspx
如果你只是感興趣的話,那就忘了這個屬性吧,在.NET 4.0以後,微軟會盡量解決掉這個屬性。