2010-06-10 64 views
23

我目前正在学习COM。我发现COM DLL是建立在传统的DLL基础上的。当我们构建COM DLL时,我们仍然依靠传统的DLL导出方法来引导我们进入内部COM协同类。传统DLL与COM DLL的区别

如果COM是用于二进制级别的组件重用,我认为传统的DLL可以达到同样的效果。它们都暴露功能,它们都是二进制的,所以转向COM方法有什么意义?

目前,我有一种感觉,传统的DLL公开方法在“”的方式,而COM DLL暴露出的“OOP”分层结构的方式方法。而面向对象的方式似乎是一种更好的方法。这是否能成为COM盛行的原因?

非常感谢。

+1

是什么让你觉得COM盛行?如果更多的DLL是经典的'c'DLL而不是COM DLL,我不会感到惊讶。 – 2010-06-10 17:16:56

+0

感谢您的评论。也许我错了。但是,似乎许多Windows功能都是基于COM构建的,比如ActiveX,OLE,甚至.NET也构建为COM服务器的集合。所以我得出了这个结论。 – smwikipedia 2010-06-11 03:29:51

回答

28

不,这里有很大的区别。 COM有一个定义良好的协议,用于创建对象,公开方法,管理内存,发布类型信息,管理线程。几乎没有任何语言不支持使用COM服务器,不管它使用什么语言编写。

您不会直接暴露自己的功能。这可能仅适用于使用C/C++编写的程序(因此它可以读取头文件),使用完全相同版本的C++编译器进行编译,并且不缺乏各种互操作问题。像暴露一个类似std :: string的C++类对象一样简单是不安全的。内存布局不保证兼容,也没有任何种类的内存所有权协议。

它可能是更多的OOPy,COM不支持继承,因为OOP很难在二进制级别兼容。这个问题需要运行时支持所有代码购买到的虚拟机,如.NET和Java。

+1

关于第二段,有相当多的语言/框架等,它们允许您在C++之外使用本机(非COM)DLL。例如,.NET通过[P/Invoke](http://msdn.microsoft.com/en-us/magazine/cc164123.aspx)有一个简单的使用interop机制。 – hemp 2010-06-22 00:34:41

+1

世界各不相同。 P/Invoke是一次一次呼叫一次的战斗。 COM服务器可以毫不费力地工作在95%的情况下。 – 2010-06-22 02:02:56

+0

什么会被视为服务潜在客户端使用它的暴露com对象的“COM服务器”? – RollRoll 2017-06-23 17:13:00

12

COM DLL只是一个具有Com特定入口点的DLL。 COM公开了用于创建com对象的类工厂,因此需要有一种方法可以访问由COM服务器实现的某个类工厂。这就是DllGetClassObject所做的。此外,COM DLL是自注册的:他们可以通知Windows他们可用的类和接口。使DLL注册的入口点是DllRegisterServer。

有几个其他入口点,但他们沿着这些线。

如果DllRegisterServer没有明确定义的入口点,则客户端将无法使DLL自行注册。这会使COM组件的安装更加复杂。

如果没有获得类工厂的标准入口点,则每个DLL都必须定义自己的入口点,并且该信息必须放入Windows注册表中,以便COM基础结构知道如何访问每个DLL的类工厂。没有理由额外的复杂性,所以入口点也是标准化的。

至于COM与“C”不同的地方,主要区别在于契约的概念。 COM鼓励程序员根据模块之间的抽象接口思考问题,而不是分层的,自上而下的功能分解。这是一种'OOP',但是这个词太宽松了,没有多大用处,IMO。面向契约的方法的优点对于像C/C++这样的强类型,静态链接语言来说是多方面的。

5

如果你想了解的原因,引入COM和它背后的理念,我强烈建议阅读From CPP to COM

7

我认为通过阅读基本COM的第一章你将有一个非常好的主意为什么使用COM。

简单来说,COM确保二进制级别的兼容性,无论您使用何种语言,您使用的是哪种版本的编译器。这不是关于“OOP”的事情,你肯定可以从DLL中暴露C++类,但它们不是“二进制兼容的”。

+0

您应该阅读“Inside OLE”。 – gonzobrains 2014-03-18 02:41:36

4

关键的区别在于COM支持二进制兼容性。

如果您添加/删除函数并重建传统的DLL,那么任何客户端应用程序在尝试使用DLL时可能会失败,因为它们是针对早期版本构建的。

COM引入了接口的概念,它是不可变的,所以不应该在构建之间进行更改等。每个COM对象都必须实现IUnknown接口,该接口包含QueryInterface方法,该方法用于向对象请求指向其他支持的接口。

COM规范确保IUnknown接口始终位于DLL中的相同位置,因此即使修改了对象以支持更多接口,仍可安全地调用QueryInterface方法。

3

想到COM的最好方法就是将它想象成你和使用你创建的对象的人之间的契约。

COM处理

  1. 如何版本的跨版本
  2. 对象如何发现你的对象,即使你的对象是在被重命名或从不同的源传来一个DLL
  3. 如何引用并破坏你的对象(关于堆)
  4. 你期望的线程工作方式以及围绕你的对象的线程/锁定的规则

COM已经成为一种标准,因为虽然您可以制作一个传统的DLL来处理上述每个项目,但在使用COM规则发送DLL时,您必须清楚说明预期的合同,此关系是为你做的

你也正确的COM暴露对象,而更传统的DLLS只是暴露功能。你经常会看到开发人员试图直接在C中模拟COM中找到的契约,通常你会看到它们在DLL中克隆了COM的方面(例如,你会看到返回函数指针结构的方法)......我的经验是如果你不使用COM来制作公共DLL,你会增加错过某些情况的几率,尤其是当版本在图片中时

+0

哦,我敢肯定我错过了一些COM处理的东西 - 请注意他们作为评论:-) – stuck 2010-06-21 02:46:54

5

DLL在Windows中有很多用途。许多类型的库代码都存储在DLL中。例如,其中一个是.net程序集,这是一个不同的野兽。

COM DLL并不比“普通二进制PE DLL”更好,因为COM DLL 也是普通DLL。使DLL成为COM DLL的原因是,除了其他事情外,可能还会公开某些与某个契约(签名)[查找条目IUnknown]相匹配的导出,甚至还有几种标准化的接口[lookup entry'dual interface']只能实例化DLL中的特定对象,还能自动发现服务,包括函数名称和参数类型。

双接口,使它非常方便的链接到脚本语言(在网络中使用,shell脚本,教育计划等),因为脚本程序员不关心严格类型。由COM DLL公开的双重接口允许脚本运行时精确地查询它期望的类型,并无缝地向用户进行适当的强制转换。这种灵活性允许构建一个完整的巨大COM基础设施,包括组件注册,DCOM(网络调用)等。它使得将COM接口提供到Windows组件(例如WMI)和办公室组件。 COM之上实现了许多其他常用接口,如ADO。

这一切都很好,但COM在任何意义上都不“占上风”。 COM DLL是少数的DLL。普通的DLL和.NET DLL非常流行。微软认为.net接口优于COM。许多unix怪胎和其他人认为dll是一个坏主意,因为它不提供运行时链接服务,这与unix共享对象总是有同样的意义。尽管是Windows开发人员,但我也认为SO提供了一个更好的选择,我希望只有一次。

2

除了已经发布的答案,COM接口的编程语言无关的方式,允许内存在一个进程的地址空间分配和释放的另一个这些对象公开的二进制数据的对象。查找编组和解组。

它还允许而不注意编码的细节,以确定空终止可能是要传递的字符串。 COM字符串被统计为UNICODE字符串。

在IDL投掷和编译类型库到DLL,和你有自我描述接口。使用普通的DLL时,您必须从外部文档了解它们具有的方法和参数。

COM标准也可以是跨平台的。 Mac版本的Office支持COM,并且已经有类似Unix和类Unix系统的实现,尽管它们从未流行过。