溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C#互操作性入門系列(一):C#中互操作性介紹

發(fā)布時間:2020-07-29 10:45:34 來源:網(wǎng)絡(luò) 閱讀:1095 作者:LearningHard 欄目:編程語言

C#互操作系列文章:

  1. C#互操作性入門系列(一):C#平臺下互操作性介紹

  2. C#互操作性入門系列(二):使用平臺調(diào)用調(diào)用Win32 函數(shù)

  3. C#互操作性入門系列(三):平臺調(diào)用中的數(shù)據(jù)封送處理

  4. C#互操作性入門系列(四):在C#中調(diào)用COM組件


本專題概要:
  • 引言

  • 平臺調(diào)用

  • C++ Interop(互操作)

  • COM Interop(互操作)



一、引言
  這個系列是在C#基礎(chǔ)知識中遺留下來的一個系列的,因為在C# 4.0中的一個新特性就是對COM互操作改進,然而COM互操作性卻是.NET平臺下其中一種互操作技術(shù),為了幫助大家更好的了解.NET平臺下的互操作技術(shù),所以才有了這個系列。然而有些朋友們可能會有這樣的疑問——“為什么我們需要掌握互操作技術(shù)的呢?” 對于這個問題的解釋就是——掌握了.NET平臺下的互操作性技術(shù)可以幫助我們在.NET中調(diào)用非托管的dll和COM組件。.NET是建立在操作系統(tǒng)的之上的一個開發(fā)框架,其中.NET 類庫中的類也是對Windows API的抽象封裝,然而.NET類庫不可能對所有Windows API進行封裝,當(dāng).NET中沒有實現(xiàn)某個功能的類,然而該功能在Windows API被實現(xiàn)了,此時我們完全沒必要去自己在.NET中自定義個類,這時候就可以調(diào)用Windows  API 中的函數(shù)來實現(xiàn),此時就涉及到托管代碼與非托管代碼的交互,此時就需要使用到互操作性的技術(shù)來實現(xiàn)托管代碼和非托管代碼更好的交互。.NET 平臺下提供了3種互操作性的技術(shù):
  1. Platform Invoke(P/Invoke),即平臺調(diào)用,主要用于調(diào)用C庫函數(shù)和Windows API

  2. C++ Introp, 主要用于Managed C++(托管C++)中調(diào)用C++類庫

  3. COM Interop, 主要用于在.NET中調(diào)用COM組件和在COM中使用.NET程序集。

下面就對這3種技術(shù)分別介紹下。                                                            
二、平臺調(diào)用
  使用平臺調(diào)用的技術(shù)可以在托管代碼中調(diào)用動態(tài)鏈接庫(Dll)中實現(xiàn)的非托管函數(shù),如Win32 Dll和C/C++ 創(chuàng)建的dll??吹竭@里,有些朋友們應(yīng)該會有疑問——在怎樣的場合我們可以使用平臺調(diào)用技術(shù)來調(diào)用動態(tài)鏈接庫中的非托管函數(shù)呢?
  這個問題就如前面引言中說講到的一樣,當(dāng)在開發(fā)過程中,.NET類庫中沒有提供相關(guān)API然而Win32 API 中提供了相關(guān)的函數(shù)實現(xiàn)時,此時就可以考慮使用平臺調(diào)用的技術(shù)在.NET開發(fā)的應(yīng)用程序中調(diào)用Win32 API中的函數(shù);
  然而還有一個使用場景就是——由于托管代碼的效率不如非托管代碼,為了提高效率,此時也可以考慮托管代碼中調(diào)用C庫函數(shù)。
2.1 在托管代碼中通過平臺調(diào)用來調(diào)用非托管代碼的步驟
(1).  獲得非托管函數(shù)的信息,即dll的名稱,需要調(diào)用的非托管函數(shù)名等信息
(2). 在托管代碼中對非托管函數(shù)進行聲明,并且附加平臺調(diào)用所需要屬性
(3). 在托管代碼中直接調(diào)用第二步中聲明的托管函數(shù)
2.2 平臺調(diào)用的調(diào)用過程
(1)  查找包含該函數(shù)的DLL,當(dāng)需要調(diào)用某個函數(shù)時,當(dāng)然第一步就需要知道包含該函數(shù)的DLL的位置,所以平臺調(diào)用的第一步也就是查找DLL,其實在托管代碼中調(diào)用非托管代碼的調(diào)用過程可以想象成叫某個人做事情,首先我們要找到那個人在哪里(即查找函數(shù)的DLL過程),找到那個人之后需要把要做的事情告訴他(相當(dāng)于加載DLL到內(nèi)存中和傳入?yún)?shù)),最后讓他去完成需要完成的事情(相當(dāng)于讓非托管函數(shù)去執(zhí)行任務(wù))。
(2) 將找到的DLL加載到內(nèi)存中。
(3) 查找函數(shù)在內(nèi)存中的地址并把其參數(shù)推入堆棧,來封送所需的數(shù)據(jù)。CLR只會在第一次調(diào)用函數(shù)時,才會去查找和加載DLL,并查找函數(shù)在內(nèi)存中的地址。當(dāng)函數(shù)被調(diào)用過一次之后,CLR會將函數(shù)的地址緩存起來,CLR這種機制可以提高平臺調(diào)用的效率。在應(yīng)用程序域被卸載之前,找到的DLL都一直存在于內(nèi)存中。
(4) 執(zhí)行非托管函數(shù)。
平臺調(diào)用的過程可以通過下圖更好地理解:
C#互操作性入門系列(一):C#中互操作性介紹
三、C++ Interop
  第二部分主要向大家介紹了第一種互操作性技術(shù),然后我們也可以使用C++ Interop技術(shù)來實現(xiàn)與非托管代碼進行交互。然而C++ Interop 方式有一個與平臺調(diào)用不一樣的地方,就是C++ Interop 允許托管代碼和非托管代碼存在于一個程序集中,甚至同一個文件中。C++ Interop 是在源代碼上直接鏈接和編譯非托管代碼來實現(xiàn)與非托管代碼進行互操作的,而平臺調(diào)用是加載編譯后生成的非托管DLL并查找函數(shù)的入口地址來實現(xiàn)與非托管函數(shù)進行互操作的。C++ Interop使用托管C++來包裝非托管C++代碼,然后編譯生成程序集,然后再托管代碼中引用該程序集,從而來實現(xiàn)與非托管代碼的互操作。 關(guān)于具體的使用和與平臺調(diào)用的比較,這里就不多介紹,我將會在后面的專題中具體介紹。
四、COM Interop
  COM(Component Object Model,組件對象模型)是微軟之前推薦的一個開發(fā)技術(shù),由于微軟過去十多年里面開發(fā)了大量的COM組件,然而不可能在使用.NET技術(shù)重寫這些COM組件實現(xiàn)的功能,所以為了解決在.NET中的托管代碼能夠調(diào)用COM組件的問題,.NET 平臺下提供了COM Interop,即COM互操作技術(shù),COM Interop不僅支持在托管代碼中使用COM組件,而且還支持想CMO組件功能托管對象。下面就這兩種支持分別做一個介紹。
4.1 在.NET中使用COM組件
在.NET中使用COM對象,主要有3種方法:
      1. 使用TlbImp工具為COM組件創(chuàng)建一個互操作程序集來綁定早期的COM對象,這樣就可以在程序中添加互操作程序集來調(diào)用COM對象

      2. 通過反射來后期綁定COM對象

      3. 通過P/Invoke創(chuàng)建COM對象或使用C++ Interop為COM對象編寫包裝類

但是我們經(jīng)常使用的都是方法一,下面介紹下使用方法一在.NET 中使用COM對象的步驟:
  1. 找到要使用的COM 組件并注冊它。使用 regsvr32.exe 注冊或注銷 COM DLL。                

  2. 在項目中添加對 COM 組件或類型庫的引用。                

添加引用時,Visual Studio 會用到Tlbimp.exe(類型庫導(dǎo)入程序),Tlbimp.exe程序?qū)⑸梢粋€ .NET Framework 互操作程序集。該程序集又稱為運行時可調(diào)用包裝 (RCW),其中包含了包裝COM組件中的類和接口。Visual Studio 將生成組件的引用添加至項目。
     3. 創(chuàng)建RCW中類的實例,這樣就可以使用托管對象一樣來使用COM對象。
下面通過一個圖更好地說明在.NET中使用COM組件的過程:
C#互操作性入門系列(一):C#中互操作性介紹
4.2 在COM中使用.NET程序集
  .NET 公共語言運行時通過COM可調(diào)用包裝(COM Callable Wrapper,即CCW)來完成與COM類型庫的交互。CCW可以使COM客戶端認為是在與普通的COM類型交互,同時使.NET組件認為它正在與托管應(yīng)用程序交互。在這里CCW是非托管COM客戶端與托管對象之間的一個代理。 CCW既可以維護托管對象的生命周期,也負責(zé)數(shù)據(jù)類型在COM和.NET之間的相互轉(zhuǎn)換。實現(xiàn)在COM使用.NET 類型的基本步驟如:
1. 在C#項目中添加互操作特性
 可以修改C#項目屬性使程序集對COM可見。右鍵解決方案選擇屬性,在“應(yīng)用程序標(biāo)簽”中選擇“程序集信息”按鈕,在彈出的對話框中選擇 “使程序集COM可見” 選項,如下圖所示:
C#互操作性入門系列(一):C#中互操作性介紹
2. 生成COM類型庫并對它進行注冊以供COM客戶端使用
在“生成”標(biāo)簽中,選中 “為COM互操作注冊”選項,如下圖:
C#互操作性入門系列(一):C#中互操作性介紹
勾選“為COM互操作注冊”選項后,Visual Studio會調(diào)用類型庫導(dǎo)出工具(Tlbexp.exe)為.NET程序集生成COM類型庫再使用程序集注冊工具(Regasm.exe)來完成對.NET程序集和生成的COM類型庫進行注冊,這樣COM客戶端可以使用CCW服務(wù)來對.NET對象進行調(diào)用了。
五、總結(jié)

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


向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI