【问题标题】:What is the ($Foo)PS project in my $Foo ATL solution for?我的 $Foo ATL 解决方案中的 ($Foo)PS 项目有什么用?
【发布时间】:2012-03-23 20:59:06
【问题描述】:

在 MSVC 中创建 ATL 项目似乎创建的不是一个而是两个项目;后者与前者命名相同,但在其名称后附加了 PS。第二个项目的目的是什么?如何判断我是否需要它?

【问题讨论】:

  • “PS”代表proxy/stub,大概有人比我更懂它的意思吧!
  • Visual Studio 2017 向导包含一个“允许合并代理/存根代码”复选框,可防止创建 PS 项目。

标签: c++ visual-studio com atl


【解决方案1】:

COM 支持跨两个不同的线程、两个不同的进程或两台不同的机器进行接口方法调用。这称为编组。两个不同的线程是最常见的情况,一个 COM 服务器通常不是线程安全的。 COM 通过将来自“错误”线程的调用编组到创建服务器的线程来为此类单线程 coclass 实现线程安全。当您编写进程外服务器时,会发生进程之间的编组。跨网络的不同机器之间称为 DCOM。

这是通过创建一个与原始界面完全相似的接口实例来实现的。但是接口的所有方法实际上都是完成调用封送工作的替代品。这是代理。在电线的另一端,有一个替代品,它看起来完全 像界面,但做的是相反的工作。这是存根。代理和存根一起工作,营造出您正在程序中进行简单方法调用的错觉。

代理的主要工作是将方法调用的参数序列化到内存缓冲区或网络数据包中。这可能很不重要,尤其是当您使用指向可变大小结构的指针时。 COM 需要帮助才能做到这一点,这就是您的 FooPS 项目的工作。当您在 .idl 文件上运行 midl.exe 时,midl 会从接口定义中自动生成代码以实现代理和存根。这通常已经足够好,但如果 IDL 中的内置关键字不足以描述您的数据,您可能需要自己实现。

最后但同样重要的是,Windows 提供了一个标准的编组器,可以编组简单的接口。旨在支持 COM 自动化定义的 COM 子集。换句话说,从 IDispatch 派生并且仅使用自动化兼容类型的接口。您只需要正确获取注册表项即可启用它,否则不需要 midl 生成的代理/存根。当然,如果您只在一个线程上进行简单的进程内调用,那么您也不需要它。这很常见。

【讨论】:

  • 真棒答案...让我很开心:)
【解决方案2】:

正如@ebutusov 所说,*PS 项目包含Proxy and Stub 的实现。它们不是标准的,而是由 MIDL 为从 ATL 服务器导出的接口生成的。这些接口在 *.IDL 文件中声明。项目的输出是 DLL。您可以阅读this article 了解更多详情。

如果您没有在 *.IDL 文件中定义任何自定义接口,或者您只定义了具有双重和 oleautomation 修饰符的接口,您可以从解决方案中删除 PS 项目。在这种情况下,将使用标准类型库编组器。

为了能够使用标准的类型库编组器,必须注册一个类型库(这是自动完成的,因为您使用的是 ATL)

【讨论】:

    【解决方案3】:

    它是代理/存根代码,其中包含在不同单元之间传输数据所需的非标准数据编组器(与线程相关)。它在调用您的 COM 对象的应用程序使用不同的 COM 线程模型时使用。 ATL/COM 向导中有一个选项可以将此代码合并到主库中。在许多常见情况下,您不必担心它(即当您的 COM dll 在客户端上下文中运行时),除非您想编写自定义编组器。

    【讨论】:

      猜你喜欢
      • 2017-06-23
      • 2010-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-04
      • 2018-02-27
      • 2015-03-08
      • 2018-07-01
      相关资源
      最近更新 更多