1. 程式人生 > 程式設計 >C#中互操作性簡介

C#中互操作性簡介

一、引言

  這個系列是在C#基礎知識中遺留下來的一個系列的,因為在C# 4.0中的一個新特性就是對COM互操作改進,然而COM互操作性卻是.NET平臺下其中一種互操作技術,為了幫助大家更好的瞭解.NET平臺下的互操作技術,所以才有了這個系列。然而有些朋友們可能會有這樣的疑問——“為什麼我們需要掌握互操作技術的呢?” 對於這個問題的解釋就是——掌握了.NET平臺下的互操作性技術可以幫助我們在.NET中呼叫非託管的dll和COM元件。.NET是建立在作業系統的之上的一個開發框架,其中.NET 類庫中的類也是對Windows API的抽象封裝,然而.NET類庫不可能對所有Windows API進行封裝,當.NET中沒有實現某個功能的類,然而該功能在Windows API被實現了,此時我們完全沒必要去自己在.NET中自定義個類,這時候就可以呼叫Windows API 中的函式來實現,此時就涉及到託管程式碼與非託管程式碼的互動,此時就需要使用到互操作性的技術來實現託管程式碼和非託管程式碼更好的互動。.NET 平臺下提供了3種互操作性的技術:

  1. Platform Invoke(P/Invoke),即平臺呼叫,主要用於呼叫C庫函式和Windows API
  2. C++ Introp,主要用於Managed C++(託管C++)中呼叫C++類庫
  3. COM Interop,主要用於在.NET中呼叫COM元件和在COM中使用.NET程式集。

下面就對這3種技術分別介紹下。

二、平臺呼叫

  使用平臺呼叫的技術可以在託管程式碼中呼叫動態連結庫(Dll)中實現的非託管函式,如Win32 Dll和C/C++ 建立的dll。看到這裡,有些朋友們應該會有疑問——在怎樣的場合我們可以使用平臺呼叫技術來呼叫動態連結庫中的非託管函式呢?

  這個問題就如前面引言中說講到的一樣,當在開發過程中,.NET類庫中沒有提供相關API然而Win32 API 中提供了相關的函式實現時,此時就可以考慮使用平臺呼叫的技術在.NET開發的應用程式中呼叫Win32 API中的函式;

  然而還有一個使用場景就是——由於託管程式碼的效率不如非託管程式碼,為了提高效率,此時也可以考慮託管程式碼中呼叫C庫函式。

2.1 在託管程式碼中通過平臺呼叫來呼叫非託管程式碼的步驟

(1). 獲得非託管函式的資訊,即dll的名稱,需要呼叫的非託管函式名等資訊

(2). 在託管程式碼中對非託管函式進行宣告,並且附加平臺呼叫所需要屬性

(3). 在託管程式碼中直接呼叫第二步中宣告的託管函式

2.2 平臺呼叫的呼叫過程

(1) 查詢包含該函式的DLL,當需要呼叫某個函式時,當然第一步就需要知道包含該函式的DLL的位置,所以平臺呼叫的第一步也就是查詢DLL,其實在託管程式碼中呼叫非託管程式碼的呼叫過程可以想象成叫某個人做事情,首先我們要找到那個人在哪裡(即查詢函式的DLL過程),找到那個人之後需要把要做的事情告訴他(相當於載入DLL到記憶體中和傳入引數),最後讓他去完成需要完成的事情(相當於讓非託管函式去執行任務)。

(2) 將找到的DLL載入到記憶體中。

(3) 查詢函式在記憶體中的地址並把其引數推入堆疊,來封送所需的資料。CLR只會在第一次呼叫函式時,才會去查詢和載入DLL,並查詢函式在記憶體中的地址。當函式被呼叫過一次之後,CLR會將函式的地址快取起來,CLR這種機制可以提高平臺呼叫的效率。在應用程式域被解除安裝之前,找到的DLL都一直存在於記憶體中。

(4) 執行非託管函式。

平臺呼叫的過程可以通過下圖更好地理解:

C#中互操作性簡介

三、C++ Interop

  第二部分主要向大家介紹了第一種互操作性技術,然後我們也可以使用C++ Interop技術來實現與非託管程式碼進行互動。然而C++ Interop 方式有一個與平臺呼叫不一樣的地方,就是C++ Interop 允許託管程式碼和非託管程式碼存在於一個程式集中,甚至同一個檔案中。C++ Interop 是在原始碼上直接連結和編譯非託管程式碼來實現與非託管程式碼進行互操作的,而平臺呼叫是載入編譯後生成的非託管DLL並查詢函式的入口地址來實現與非託管函式進行互操作的。C++ Interop使用託管C++來包裝非託管C++程式碼,然後編譯生成程式集,然後再託管程式碼中引用該程式集,從而來實現與非託管程式碼的互操作。 關於具體的使用和與平臺呼叫的比較,這裡就不多介紹,我將會在後面的專題中具體介紹。

四、COM Interop

  COM(Component Object Model,元件物件模型)是微軟之前推薦的一個開發技術,由於微軟過去十多年裡面開發了大量的COM元件,然而不可能在使用.NET技術重寫這些COM元件實現的功能,所以為了解決在.NET中的託管程式碼能夠呼叫COM元件的問題,.NET 平臺下提供了COM Interop,即COM互操作技術,COM Interop不僅支援在託管程式碼中使用COM元件,而且還支援想CMO元件功能託管物件。下面就這兩種支援分別做一個介紹。

4.1 在.NET中使用COM元件

在.NET中使用COM物件,主要有3種方法:

  1. 使用TlbImp工具為COM元件建立一個互操作程式集來繫結早期的COM物件,這樣就可以在程式中新增互操作程式集來呼叫COM物件
  2. 通過反射來後期繫結COM物件
  3. 通過P/Invoke建立COM物件或使用C++ Interop為COM物件編寫包裝類

但是我們經常使用的都是方法一,下面介紹下使用方法一在.NET 中使用COM物件的步驟:

1.找到要使用的COM 元件並註冊它。使用 regsvr32.exe 註冊或登出 COM DLL。
2.在專案中新增對 COM 元件或型別庫的引用。

  • 新增引用時,Visual Studio 會用到Tlbimp.exe(型別庫匯入程式),Tlbimp.exe程式將生成一個 .NET Framework 互操作程式集。該程式集又稱為執行時可呼叫包裝 (RCW),其中包含了包裝COM元件中的類和介面。Visual Studio 將生成元件的引用新增至專案。

3. 建立RCW中類的例項,這樣就可以使用託管物件一樣來使用COM物件。

下面通過一個圖更好地說明在.NET中使用COM元件的過程:

C#中互操作性簡介

4.2 在COM中使用.NET程式集

  .NET 公共語言執行時通過COM可呼叫包裝(COM Callable Wrapper,即CCW)來完成與COM型別庫的互動。CCW可以使COM客戶端認為是在與普通的COM型別互動,同時使.NET元件認為它正在與託管應用程式互動。在這裡CCW是非託管COM客戶端與託管物件之間的一個代理。 CCW既可以維護託管物件的生命週期,也負責資料型別在COM和.NET之間的相互轉換。實現在COM使用.NET 型別的基本步驟如:

1. 在C#專案中新增互操作特性

可以修改C#專案屬性使程式集對COM可見。右鍵解決方案選擇屬性,在“應用程式標籤”中選擇“程式集資訊”按鈕,在彈出的對話方塊中選擇 “使程式集COM可見” 選項,如下圖所示:

C#中互操作性簡介

2. 生成COM型別庫並對它進行註冊以供COM客戶端使用

在“生成”標籤中,選中 “為COM互操作註冊”選項,如下圖:

C#中互操作性簡介

  勾選“為COM互操作註冊”選項後,Visual Studio會呼叫型別庫匯出工具(Tlbexp.exe)為.NET程式集生成COM型別庫再使用程式集註冊工具(Regasm.exe)來完成對.NET程式集和生成的COM型別庫進行註冊,這樣COM客戶端可以使用CCW服務來對.NET物件進行呼叫了。

五、總結

  介紹到這裡,本專題的內容就結束,本專題主要對.NET 提供的互操作的技術做了一個總的概括,在後面的專題中將會對具體的技術進行詳細的介紹和給出一些簡單的使用例子。

以上就是C#中互操作性簡介的詳細內容,更多關於c# 互操作性的資料請關注我們其它相關文章!