传统DLL和COM DLL之间的区别

时间:2010-06-10 17:07:05

标签: c++ com

我目前正在学习COM。我发现COM DLL是基于传统的DLL基础结构构建的。当我们构建COM DLL时,我们仍然依赖传统的DLL导出方法来引导我们进入内部COM共同类。

如果COM用于二进制级别的组件重用,我认为传统的DLL可以实现相同的功能。它们都暴露了函数,它们都是二元函数,那么转向COM方法有什么意义呢?

目前,我感觉传统的DLL以“ flat ”方式公开方法,而COM DLL以“ OOP ”层次结构方式公开方法。 OOP方式似乎是一种更好的方法。这可能是COM占上风的原因吗?

非常感谢。

8 个答案:

答案 0 :(得分:34)

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

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

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

答案 1 :(得分:15)

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 ++)来说是多方面的。

答案 2 :(得分:8)

我认为通过阅读 Essential COM 的第一章,您将非常了解使用COM的原因。

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

答案 3 :(得分:5)

如果您想了解介绍COM的原因及其背后的理念,我强烈建议您阅读From CPP to COM

答案 4 :(得分:5)

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

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

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

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

答案 5 :(得分:5)

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

COM DLL并不比“普通二进制PE DLL”好,因为COM DLL 也是一个普通的DLL 。使DLL成为COM DLL的原因是,除了其他东西之外,某些导出符合特定合同(签名)[查找条目IUnknown],甚至是几种类型的封装接口[查找条目'双接口']仅实例化DLL内的特定对象,但也自动发现服务,包括函数名称和参数类型。

双接口使得链接到脚本语言(用于Web,shell脚本,教育程序等)变得非常方便,因为脚本程序员不关心严格的输入。 COM DLL公开的双接口允许脚本运行时准确地查询它所期望的类型,并对用户无缝地执行适当的转换。

这种灵活性允许构建整个巨大的COM基础设施,包括组件注册,DCOM(通过网络调用)等。它使得将COM接口提供到Windows组件(例如WMI)和办公组件中相当方便。 。在COM之上实现了许多其他流行的接口,例如ADO。

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

答案 6 :(得分:4)

考虑COM的最佳方式是将其想象为您与使用您创建的对象的人之间的契约。

COM处理

  1. 如何跨版本对象进行版本化
  2. 如何发现您的对象,即使您的对象位于重命名的DLL或来自其他来源的DLL中
  3. 如何引用和销毁你的对象(关于堆)
  4. 您希望线程如何工作,以及围绕对象进行线程/锁定的规则
  5. COM已经成为标准,因为虽然你可以制作一个处理上述每个项目的传统DLL,但是当你发送你的DLL时你必须明确表达预期的合同

    通过使用COM的规则,这个清晰度是为你完成的

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

答案 7 :(得分:3)

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

它还允许传递字符串而不必关注编码细节以确定空终止符的位置。 COM字符串计为UNICODE字符串。

抛出IDL并将类型库编译到DLL中,并且您具有自描述接口。使用普通的DLL,您必须从外部文档中了解它们具有哪些方法以及它们采用的参数。

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