[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

相关文章
相关标签/搜索