C++ 传统DLL与COM DLL的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3016683/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:47:10  来源:igfitidea点击:

The difference between traditional DLL and COM DLL

c++com

提问by smwikipedia

I am currently studying COM. I found that COM DLL is kind of built upon the traditional DLL infrastructure. When we build COM DLLs, we still rely on the traditional DLL export methods to lead us to the internal COM co-classes.

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

If COM is for component reusing at the binary level, I think the traditional DLL can achieve the same thing. They both expose functions, they are both binary, so what's the point of turning to COM approach?

如果 COM 是为了组件在二进制层面的复用,我认为传统的 DLL 可以达到同样的效果。它们都公开函数,它们都是二进制的,那么转向 COM 方法有什么意义呢?

Currently, I have the feeling that the traditional DLL expose methods in a "flat" manner, while the COM DLL expose methods in an "OOP" hierarchy manner. And the OOP manner seems to be a better approach. Could this be the reason why COM prevails?

目前,我觉得传统的 DLL 以“平面”方式公开方法,而 COM DLL 以“ OOP”层次结构方式公开方法。而 OOP 方式似乎是一种更好的方法。这可能是COM盛行的原因吗?

Many thanks.

非常感谢。

回答by Hans Passant

No, there's a Big difference. COM has a well defined protocols for creating objects, exposing methods, managing memory, publishing type information, managing threading. There is practically no language left that doesn't support using a COM server, no matter what language it was written in.

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

You will not get that from exposing your own functions directly. That will likely be only usable from a program written in C/C++ (so it can read your header files), compiled with the exact same version of the C++ compiler and no lack of all kinds of interop problems. Something as simple as exposing a C++ class object like std::string is not safe. Neither the memory layout is guaranteed to be compatible, nor is there any kind of memory ownership protocol.

你不会通过直接公开你自己的函数来获得它。这可能只能从用 C/C++ 编写的程序中使用(因此它可以读取您的头文件),使用完全相同版本的 C++ 编译器编译并且不缺乏各种互操作问题。暴露像 std::string 这样的 C++ 类对象这样简单的事情是不安全的。既不保证内存布局兼容,也不保证任何类型的内存所有权协议。

It could well be more OOPy, COM doesn't support inheritance because OOP is so hard to get compatible at the binary level. That problem requires runtime support that all code buys into, VMs like .NET and Java.

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

回答by David Gladfelter

A COM DLL is simply a DLL with Com-specific entry points. COM exposes class factories for creating com objects, so there needs to be a way of getting access to one of the class factories implemented by a COM server. That's what DllGetClassObject does. Furthermore, COM DLL's are self-registering: they can notify Windows of their available classes and interfaces. The Entry point for having the DLL register itself is DllRegisterServer.

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

There are a couple of other entry points, but they are along these lines.

还有其他几个入口点,但它们都在这些方面。

If there wasn't a well-defined entry point for DllRegisterServer, then clients wouldn't be able to cause DLL's to self-register. It would make installation of COM components more complex.

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

If there weren't a standardized entry point for getting class factories, then each DLL would have to define its own entry point and that information would have to be put in the Windows Registry so that the COM infrastructure would know how to access each DLL's class factory. There's no justification for the extra complexity, so that entry point is also standarized.

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

As to where COM differs from 'C', the main difference is the concept of contracts. COM encourages programmers to think in terms of abstract interfaces between modules rather than a hierarchical, top-down decomposition of functionality. This is one kind of 'OOP', but that term is too loose to be of much use, IMO. Advantages of the contract-oriented approach are manifold for strongly-typed, statically linked languages like C/C++.

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

回答by Baiyan Huang

I think by reading the first chapter of Essential COMby Don Box linked here, you'll have a very good idea of why we use COMs.

我认为通过阅读此处链接的 Don Box 撰写的Essential COM的第一章,您将对我们使用 COM 的原因有一个很好的了解。

To summarize: COM ensures compatibility at the binary level, no matter what language you used, or what version compiler you used. It is not about the "OOP" thing, you sure could expose C++ class from a DLL, but they are not "binary compatible."

总结一下:COM 确保二进制级别的兼容性,无论您使用什么语言,或者您使用什么版本的编译器。这与“OOP”无关,您肯定可以从 DLL 公开 C++ 类,但它们不是“二进制兼容的”。

回答by robaker

The key difference is that COM enables binary compatibility.

主要区别在于 COM 支持二进制兼容性。

If you add/remove functions and rebuild a traditional DLL then any client applications will probably fail when they try and use the DLL because they were built against the earlier version.

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

COM introduced the concept of interfaces, which are immutable so should not be altered between builds, etc. Every COM object must implement the IUnknown interface which contains the QueryInterface method which is used to ask the object for pointers to other supported interfaces.

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

The COM specification ensures that the IUnknown interface is always in the same place in the DLL so even if an object is revised to support more interfaces the QueryInterface method can still be called safely.

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

回答by Pavel Radzivilovsky

DLL has many uses in windows. Many types of library code are stored in DLL. One of these, for example, is .net assemblies, which is a different beast.

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

COM DLL is not better than "plain binary PE DLL" because COM DLL is also a plain DLL. What makes DLL a COM DLL is exposing, possibly in addition to other things, certain exports that match a certain contract (signature) [lookup entry IUnknown], or even several types of canonized interfaces [lookup entry 'dual interface'] that allow not only instantiation of specific objects inside the DLL but also automated discovery of services, including function names and parameter types.

COM DLL 并不比“普通二进制 PE DLL”好,因为 COM DLL也是普通 DLL。使 DLL 成为 COM DLL 的原因可能除了其他内容外,还公开了与特定合同(签名)[查找条目 IUnknown] 匹配的某些导出,甚至几种类型的规范化接口 [查找条目“双接口”] 不允许不仅可以实例化 DLL 内的特定对象,还可以自动发现服务,包括函数名称和参数类型。

The dual interfaces make it very handy to link to scripting languages (used in web, shell scripts, educational programs, etc) because the script programmers do not care about strict typing. A dual interface exposed by COM DLL allows the scripting runtime to query exactly what types it expects and do the appropriate casts, seamlessly to the user.

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

This flexibility allowed a whole gigantic COM infrastructure to be built upon, including Component Registration, DCOM (invocation over network), etc. It made it rather convenient to provide COM interfaces into windows components (WMI, for example) and office components. Many other popular interfaces were implemented above COM, such as ADO.

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

All this is good, but COM does not "prevail" in any sense. COM DLLs are minority of DLLs. Plain DLLs and .NET DLLs are very popular. Microsoft considers .net interfaces superior to COM. Many unix freaks and others consider DLLs to be a bad idea altogether, as it does not provide run-time linking services in the same sense that unix shared objects always had. Despite being a windows developer, I also think SOs provide a superior alternative, and I hope to have them once.

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

回答by Nemanja Trifunovic

If you want to learn about the reasons for introducing COM and the philosophy behind it, I strongly recommend reading From CPP to COM

如果你想了解引入 COM 的原因及其背后的哲学,我强烈推荐阅读From CPP to COM

回答by stuck

The best way to think of COM is to imagine it as a contract between you and the person using the object you create.

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

COM handles

COM 句柄

  1. how to version your object across releases
  2. how to discover your object, even if your object is in a DLL that gets renamed or came from a different source
  3. how to reference and destroy your object (with respect to heaps)
  4. how you expect threading to work, and the rules surrounding threading/locking for your object
  1. 如何跨版本对对象进行版本控制
  2. 如何发现您的对象,即使您的对象位于已重命名或来自不同来源的 DLL 中
  3. 如何引用和销毁您的对象(关于堆)
  4. 您期望线程如何工作,以及围绕对象的线程/锁定规则

COM has become a standard because while you could make a traditional DLL that handles each of the above items you'd have to articulate the expected contract when you ship your DLL

COM 已成为一种标准,因为虽然您可以制作一个传统的 DLL 来处理上述每个项目,但您必须在交付 DLL 时阐明预期的合同

by using the rules of COM, this articulation is done for you

通过使用 COM 的规则,这个关节是为你完成的

you are also correct that COM exposes objects while more traditional DLLS just expose functions. you'll often see developers try to emulate the contracts found in COM in straight C, usually you'll see them clone aspects of COM in their DLL (for example you'll see methods that return structs of function pointers)... my experience is if you dont use COM for making a public DLL you're increasing the odds of miss some cases, especially when versioning is in the picture

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

回答by Ron Ruble

In addition to the answers already posted, COM interfaces expose binary data objects in a programming language independent manner, that allows memory for these objects to be allocated in one process address space and freed in another. Lookup marshalling and unmarshalling.

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

It also allows strings to be passed without paying attention to details of encoding to determine where a null-terminator might be. COM strings are counted UNICODE strings.

它还允许在不注意编码细节的情况下传递字符串以确定空终止符可能在哪里。COM 字符串被计算为 UNICODE 字符串。

Throw in IDL and compile the type library into the DLL, and you have self-describing interfaces. With plain DLLs, you have to know from the external docs what methods they have and the parameters they take.

加入 IDL 并将类型库编译成 DLL,您就拥有了自描述接口。对于普通 DLL,您必须从外部文档中了解它们具有哪些方法以及它们采用的参数。

The COM standard can be cross-platform, as well. Mac versions of Office support COM, and there have been implementations for Unix and Unix-like systems, although they have never been popular.

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