天天看點

.NET簡談互操作(七:資料封送之介紹)

1:

.NET簡談互操作(七:資料封送之介紹)

在托管代碼調用非托管代碼的時候,資料經曆了很複雜的封送。由于托管的資料類型與非托管的資料類型記憶體結構可能是不一樣的,要想将托管資料參數傳遞到非托管代碼中,并且能成功的接受到非托管的傳回值,我們需要很嚴格的按照雙方的資料類型約定來才行。比如在C++中的Char*是一個字元指針,當我們想要将字元串傳遞到非托管代碼中時,我們需要考慮怎麼将參數無差錯的封送到非托管代碼。而在托管C#中的String類型是一個引用類型,兩者有相同點,也有不同點。

在我們用.NET/PInvoke進行Win32API的調用的時候,大多數的情況下我們是需要傳遞某種結構類型給API,然後在接受傳回值;在資料封送的過程中,有些概念是我們平時不曾碰見的。.NET資料封送很智能,CLR的封送拆收器能通過識别我們傳遞的資料類型情況進行自動選擇封送資料的方式,比如我們将一個Class的類類型傳遞給非托管API,預設的Class類是不能進行互操作使用的,必須加上相應的特性進行标記,編譯器編譯的時候能識别出這是要進行封送的資料類型;将Class類型進行封送時,封送拆收器會進行判斷,如果我們傳遞給非托管代碼的Class中的所有内部對象都是平台資料類型,那麼CLR會将這個對象在記憶體中鎖定,然後直接将記憶體位址封送給非托管代碼,非托管代碼直接對這資料進行操作。這是封送引用位址的方式,如果我們傳遞給非托管API的是非平台類型,那麼CLR的封送拆收收器會将我們的托管類型複制出來進行非托管類型轉換,然後将轉換後的資料傳遞給非托管,這樣的過程是複制資料的過程。互操作的資料封送基本上就是這兩種,1資料的複制封送,2資料的記憶體位址封送;

下面我們用一副圖來表達我上面所說的原理。

2:

.NET簡談互操作(七:資料封送之介紹)

如果托管的資料類型與非托管的資料類型在記憶體中是等價的,那麼CLR進行封送的方式會很簡單。如果托管的資料類型與非托管的資料類型是不等價的,那麼CLR會進行相應複制轉換操作,當然這樣會丢失資料記憶體洩漏都是有可能的,但是我們不用怕,.NET為我們做好了很好的互操作橋梁,我們隻要對要封送的資料進行一系列的設定就能很成功的進行資料封送了;

總結:這篇文章主要給大家介紹一下,關于托管與非托管的資料封送相關的概念,下面我們将學習互操作的資料封送;