關於Marshal 類的整理


在兩個不同的實體(兩個線程或者進程甚至機器、在Managed和Unmanaged之間)進行方法調用和參數傳遞的時候,具體的調用方法和參數的內存格式可能需要一定的轉換,這個轉換的過程叫做Marshal。

Marshal就是把一個結構(類)序列化成一段內存,然后送到另一個進程(.net中Application domain)中供另一個進程中的函數使用。
比如你的一個結構

struct{
Pen pen;
}s; s是一個指向已有的Pen對象的引用,當你把s傳給本進程中的一個函數f時,f可以很容易地找到pen的實際對象,但如果你把s傳到另外一個進程時,甚至是另外一台機器上的進程時,這個進程就沒辦法找到pen的實際內容。Marshal技術則可以把pen對象中的所有實際內容按規則放到一個緩沖中,(所有的引用或指針都要轉換成實際對象)然后把緩沖中的內容送到另一個進程,函數調用完成再用同樣方式把結果返回來。
在RPC,Interop,COM中Marshal應用很多。

Marshal 類提供了一個方法集,這些方法用於分配非托管內存、復制非托管內存塊、將托管類型轉換為非托管類型,此外還提供了在與非托管代碼交互時使用的其他雜項方法。

類別 成員
高級封送處理

GetManagedThunkForUnmanagedMethodPtrGetUnmanagedThunkForManagedMethodPtrNumParamBytes


COM 庫函數

BindToMonikerGetActiveObject


COM 實用工具

ChangeWrapperHandleStrengthCreateWrapperOfTypeGetComObjectDataGetComSlotForMethodInfoGetEndComSlot

GetMethodInfoForComSlotGetStartComSlotReleaseComObjectSetComObjectData


數據轉換

托管到非托管:CopyGetComInterfaceForObjectGetIDispatchForObjectGetIUnknownForObjectStringToBSTRStringToCoTaskMemAnsi

StringToCoTaskMemAutoStringToCoTaskMemUniStringToHGlobalAnsiStringToHGlobalAutoStringToHGlobalUniStructureToPtr

UnsafeAddrOfPinnedArrayElement

非托管到托管:CopyGetObjectForIUnknownGetObjectForNativeVariantGetObjectsForNativeVariantsGetTypedObjectForIUnknown

GetTypeForITypeInfoPtrToStringAnsiPtrToStringAutoPtrToStringBSTRPtrToStringUni

屬性:SystemDefaultCharSizeSystemMaxDBCSCharSize


直接讀取和寫入 ReadByteReadInt16ReadInt32ReadInt64ReadIntPtrWriteByteWriteInt16WriteInt32WriteInt64WriteIntPtr
錯誤處理 COM:GetHRForExceptionThrowExceptionForHR

Win32:GetLastWin32ErrorGetExceptionCodeGetExceptionPointers

兩者:GetHRForLastWin32Error


承載實用工具 GetThreadFromFiberCookie
IUnknown AddRefQueryInterfaceRelease
內存管理 COM:AllocCoTaskMemReAllocCoTaskMemFreeCoTaskMemFreeBSTR

Win32:AllocHGlobalReAllocHGlobalFreeHGlobal

兩者:DestroyStructure


平台調用實用工具 PrelinkPrelinkAllGetHINSTANCE
結構檢查 OffsetOfSizeOf
類型信息

GenerateGuidForTypeGenerateProgIdForTypeGetTypeInfoNameGetTypeLibGuidGetTypeLibGuidForAssemblyGetTypeLibLcid

GetTypeLibNameIsComObjectIsTypeVisibleFromCom

 

特別注意:Marshal.PtrToStringAuto方法:分配托管 String,並從非托管內存中存儲的字符串向其復制第一個空字符之前的所有字符。

 

例1、
public struct ImageDataMsg 

public char DataType; 
public int Srv_index; 
public char ConvertType; 
//這個個地方要指定長度,這樣就可以得到結構體的正確長度了 
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] 
public int[] VecLayer;//需要那幾個圖層。 
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] 
public int[] GridLayer;//需要那幾個柵格圖層 
public int Scale_index;//需要的是那個比例尺的圖像 
public int x_pos; 
public int y_pos; 
public int ClientArea_x; 
public int ClientArea_y; 

//使用這個方法將你的結構體轉化為bytes數組 
public static byte[] Struct2Bytes(ImageDataMsg obj) 

int size = Marshal.SizeOf(obj); 
byte[] bytes = new byte[size]; 
try 

IntPtr ptr = Marshal.AllocHGlobal(size); 
Marshal.StructureToPtr(obj, ptr, false); 
Marshal.Copy(ptr, bytes, 0, size); 
Marshal.FreeHGlobal(ptr); 
return bytes; 

catch (Exception ee) 

MessageBox.Show(ee.Message); 
return bytes; 



//使用這個方法將byte數組轉化為結構體 
public static object BytesToStuct2(byte[] bytes, ImageDataMsg type) 

//得到結構體的大小 
int size = Marshal.SizeOf(type); 
//byte數組長度小於結構體的大小 
if (size > bytes.Length) 

//返回空 
return null; 

//分配結構體大小的內存空間 
IntPtr structPtr = Marshal.AllocHGlobal(size); 
//將byte數組拷到分配好的內存空間 
Marshal.Copy(bytes, 0, structPtr, size); 
//將內存空間轉換為目標結構體 
object obj = Marshal.PtrToStructure(structPtr, typeof(ImageDataMsg)); 
//釋放內存空間 
Marshal.FreeHGlobal(structPtr); 
//返回結構體 
return obj; 
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM