最近在研究产品的架构代码,发现其中涉及到Com组件技术,即项目中的C# Project会通过Com接口来调用C++ Project中的方法,研究一下,实现一个小的例子,供自己学习。
一. 什么是COM Interop?
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++代码中的方法。
二. 示例步骤:
简单说明,这里COM组件由ATL COM开发,IDE为Visual Studio 2005,步骤如下:
1. 实现一个简单的ATL COM服务器
A. 创建一个新的Visual C++ ATL 项目,名字:MyComServer。
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
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