[COM Interop學習小結]實現一個C#調用C++的示例

  最近在研究產品的架構代碼,發現其中涉及到Com組件技術,即項目中的C# Project會經過Com接口來調用C++ Project中的方法,研究一下,實現一個小的例子,供本身學習。html

一. 什麼是COM Interop?java

  COM Interop 是一種讓 .NET Framework 的程序可以和 COM 的程序相互操做的一種橋接技術[維基百科]。它可讓 .NET Framework 的程序使用 COM 組件,也可讓 COM 程序使用 .NET Framework 的組件。例如像咱們的產品中,它可讓C#去調用C++的方法,C++去調用C#的方法。編程

  這裏涉及到一個概念,COM組件,COM技術是開發組件的一種,COM標準由微軟定義,COM組件能夠是一個動態鏈接庫(DLL), 被稱爲進程內組件(in-of-process component),也能夠是一個可執行程序(EXE),被稱爲進程外組件(out-of-process component)。COM對象是創建在二進制可執行代碼級的基礎上,而C++等語言中的對象是創建在源代碼級基礎上的,所以COM對象是語言無關的服務器

  這一特性使用不一樣編程語言開發的組件對象進行交互成爲可能。架構

  這裏咱們討論其中一個簡單例子:C#調用C++代碼中的方法。app

二. 示例步驟:編程語言

  簡單說明,這裏COM組件由ATL COM開發,IDE爲Visual Studio 2005,步驟以下:學習

  1. 實現一個簡單的ATL COM服務器spa

    A. 建立一個新的Visual C++ ATL 項目,名字:MyComServer。.net

    B. 向MyComServer中添加一個新類,這裏爲了開發方便,推薦使用IDE的add->class,選擇ATL Simple Object,名字:MyTest,可看到IDE自動爲咱們生成一個COM Class CMyTest。

    C. 在類視圖中,爲MyTest的接口添加方法,名字:DoSomething,其餘默認,生成後能夠根據須要添加DoSomething的方法內容。

    這時IDE已經爲咱們作了不少工做,可看到CMyTest的聲明以下:    

 1 class ATL_NO_VTABLE CMyTest :
 2     public CComObjectRootEx<CComSingleThreadModel>,
 3     public CComCoClass<CMyTest, &CLSID_MyTest>,
 4     public IDispatchImpl<IMyTest, &IID_IMyTest, &LIBID_MyComServerLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
 5 {
 6 public:
 7     CMyTest()
 8     {
 9     }
10 
11 DECLARE_REGISTRY_RESOURCEID(IDR_MYTEST)
12 
13 
14 BEGIN_COM_MAP(CMyTest)
15     COM_INTERFACE_ENTRY(IMyTest)
16     COM_INTERFACE_ENTRY(IDispatch)
17 END_COM_MAP()
18 
19 
20 
21     DECLARE_PROTECT_FINAL_CONSTRUCT()
22 
23     HRESULT FinalConstruct()
24     {
25         return S_OK;
26     }
27 
28     void FinalRelease()
29     {
30     }
31 
32 public:
33     STDMETHOD(DoSomething)(void);
34 };

    DoSomething方法的實現以下:

1 STDMETHODIMP CMyTest::DoSomething(void)
2 {
3     // TODO: Add your implementation code here
4     
5     wprintf_s(_T("Hello, I'm here!"));
6 
7     return S_OK;
8 }

  2. 使用 Tlbimp 轉換 COM DLL

  如今有了 COM DLL,讓咱們來看看如何從一個託管客戶端訪問它。打開 Visual Studio 命令提示,而後轉到建立 COM DLL 的目錄。如今運行如下命令:

tlbimp MSDNCOMServer.dll
   Tlbimp.exe 是 .NET Framework SDK 中附帶的類型庫導入程序。此命令輸出一個名爲MyComServerLIB.dll的託管 DLL,該 DLL 做爲非託管 COM DLL 的託管包裝。
  
  關於Tlbimp.exe的做用,能夠參加如下圖:
   Consuming COM Components from .NET applications
  其實就.NET Application不能直接訪問C++開發的COM組件編譯出的MyComServer.dll,所以須要經過Tlbimp.exe生成一個Com組件的託管DLL,C#代碼能夠直接調用這一MyComServerLIB.dll,使用其中的類和方法。
  這裏要注意是 RCW(Runtime Callable Wrapper),其做用是當.NET Application在運行時調用非託管代碼(本例中是C++)的方法時, runtime建立一個runtime callable wrapper (RCW)。RCW抽象了託管代碼和非託管代碼引用機制的不一樣,可以對非託管代碼的對象進行管理。Runtime還建立了一個COM callable wrapper (CCW)來實現其逆過程,使得COM的客戶可以無縫的調用.NET對象的方法。這裏不深刻探討。
  
  3. 實現一個C# Project去調用C++方法
  這裏很簡單,以下:
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Text;
 4 using MyComServerLib;
 5 
 6 namespace MyComClient
 7 {
 8     class Program
 9     {
10         static void Main(string[] args)
11         {
12             MyTestClass test = new MyTestClass();
13             test.DoSomething();
14         }
15     }
16 }

  執行此C#程序,便可看到"Hello, I'm here!"的輸出信息,證實調用成功!!

 

三. 小結

  因爲時間有限,昨天開始研究COM Interop,到今晚剛剛實現一個成功的例子,對COM技術的認識確定還有不少問題,這裏作下總結,也但願之後能繼續完善。

  在兩天的時間裏,上網找到了不少很好的參考資料,以下:

  1. 示例實現主要參考的文章

      http://msdn.microsoft.com/zh-cn/magazine/cc163494.aspx

  2. Understanding Classic COM Interoperability With .NET Applications

    http://www.codeproject.com/Articles/990/Understanding-Classic-COM-Interoperability-With-NE

     3. COM組件簡介

    http://www.cppblog.com/3522021224/archive/2007/06/22/26803.html

     4. RCW的介紹

    http://www.blogjava.net/davidgw/archive/2007/07/25/132240.html

 

 

  對於COM Interop技術,本身已經有了初步瞭解,有助於本身更加了解項目中的COM應用。

  明天能夠進入下一個學習階段啦,開始Adapter的學習!加油!晚安:-)

 

  Best Regards

  Kevin Song

相關文章
相關標籤/搜索