原 C 與非託管 封送和自動封送

2022-07-20 14:24:15 字數 1247 閱讀 8359

之前說到了如何從c函式宣告通過簡單的查詢替換生成乙份c#的靜態引用宣告(c#與非託管——初體驗),因為只是簡單說明,所以全部採用的是基礎型別匹配和自動封送。自動封送雖然能省去我們不少編碼時間,但如果不理解自動封送背後的實際行為,那就如同看魔術師的黑盒子,知其然不知其所以然。而且,自動封送也不是永遠有效的萬能藥,因此這裡記錄一下封送相關的理解。

針對string,可以使用marshal.stringtohglobalansi、marshal.stringtohglobalauto、marshal.stringtohglobaluni把string封送到非託管函式,之後需要呼叫marshal.freehglobal釋放記憶體;或者使用marshal.ptrtostringansi、marshal.ptrtostringauto、marshal.ptrtostringuni從非託管函式裡面取出string。

針對byte(或基礎型別的陣列),可以使用marshal.copy從byte拷貝封送到非託管函式或者從非託管函式拷貝封送到byte。此外從byte封送到非託管函式還可以採取固定記憶體直接傳送byte的原始位址(省去了申請記憶體和拷貝的開銷,速度更快),方法是使用gchandle並指定gchandletype.pinned型別。

針對委託,可以使用marshal.getfunctionpointerfordelegate從delegate封送到非託管函式,或者使用marshal.getdelegateforfunctionpointer從非託管函式裡面取出。和byte一樣,在封送到非託管函式時需要確保gc不要**委託(需要保持引用但不需要pinned)。

針對結構體,可以在c#中按一樣的順序和對應的資料型別宣告乙個同樣的struct(只能使用基礎型別和固定長度的陣列),並且標記structlayout的layoutkind.sequential屬性,然後使用marshal.structuretoptr和marshal.ptrtostructure進行封送。

c#的物件不能在native中進行處理,只能儲存以待之後再傳回給c#呼叫,儲存的方式為c#用gchandle引用物件,然後把gchandle轉成intptr,傳給native作為指標儲存。

當c#宣告的extern函式返回型別和引數型別中有託管型別時(如string、byte、委託等),就會進行自動封送處理,因此可以省寫大部分的封送**。不過有幾種情況還是需要手動進行封送的,如:

string的編碼是utf8之類的非ansi非utf16編碼,則必須手動進行封送同時轉換編碼。

委託轉換成函式指標的操作比較耗時,如果有頻繁的對同一委託進行封送呼叫,則預存轉換後的結果能夠很顯著的提公升效能。

C 託管資源與非託管資源

在.net 程式設計環境中,系統的資源分為託管資源和非託管資源。託管資源 net平台中,clr為程式設計師提供了一種很好的記憶體管理機制,使得程式設計師在編寫 時不要顯式的去釋放自己使用的記憶體資源 這些在先前c和c 中是需要程式設計師自己去顯式的釋放的 這種管理機制稱為gc garbage col...

C 託管資源 與 非託管資源

託管資源一般是指被clr控制的記憶體資源,這些資源的管理可以由clr來控制,net可以自動進行 主要是指託管堆上分配的記憶體資源。例如程式中分配的物件,作用域內的變數等 非託管資源 不受clr控制和管理的資源,比如檔案流,資料庫的連線,網路連線,系統的視窗控制代碼,印表機資源等,可以認為作業系統資源...

C 託管資源和非託管資源

託管資源指的是.net可以自動進行 的資源,主要是指託管堆上分配的記憶體資源。託管資源的 工作是不需要人工干預的,有.net執行庫在合適呼叫垃圾 器進行 非託管資源指的是.net不知道如何 的資源,最常見的一類非託管資源是包裝作業系統資源的物件,例如檔案,視窗,網路連線,資料庫連線,畫刷,圖示等。這...