什么是我的$Foo ATL解决方案中的($Foo)PS项目用于?

31
在MSVC中创建ATL项目似乎会创建两个项目;后者的名称与前者相同,但名称末尾附加了“PS”。第二个项目的目的是什么,我如何确定是否需要它?

3
“PS”代表代理/存根,可能有人比我更了解它的含义! - Yakov Galka
2
Visual Studio 2017向导包括一个复选框“允许合并代理/存根代码”,它可以防止创建PS项目。 - Mark Ransom
3个回答

43

COM支持在两个不同的线程、两个不同的进程或两个不同的机器之间进行接口方法调用。 这被称为封送。其中,两个不同的线程是最常见的情况,因为COM服务器通常不是线程安全的。对于这样的单线程coclass,COM通过将调用从“错误”的线程封送到创建服务器的线程来实现线程安全性。当您编写一个独立进程的服务器时,会发生进程间封送。跨网络连接的不同计算机之间的封送称为DCOM。

这是通过创建一个与原始接口完全相同的接口实例来实现的。但是,接口的所有方法实际上都是代替品,它们执行封送调用的工作。这是代理。在另一端的线路上有一个看起来完全相同的代替品,但却执行相反的工作。这是存根。代理和存根共同工作,创造了一个假象,使您的程序似乎正在进行简单的方法调用。

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

最后,Windows提供了一个标准的封送程序,可以封送简单的接口。它被设计用于支持由COM自动化定义的COM子集。换句话说,它适用于继承自IDispatch并且仅使用自动化兼容类型的接口。只需正确设置注册表条目即可启用它,并且不需要midl生成的代理/存根。当然,如果您仅在一个线程上进行简单的进程内调用,则也不需要它。这是非常常见的。


5
非常好的回答,让我今天过得愉快 :) - Houston

10
正如@ebutusov所说,*PS项目包含有关代理和存根的实现。它们不是标准的,而是由MIDL为从您的ATL服务器导出的接口生成的。这些接口在*.IDL文件中声明。该项目的输出是DLL。您可以阅读此文章以获取更多详细信息。
如果您的*.IDL文件中没有定义任何自定义接口或仅定义了带有双重和oleautomation修饰符的接口,则可以从解决方案中删除PS项目。在这种情况下,将使用标准类型库编组程序。
为了能够利用标准类型库编组程序,必须注册类型库(由于您正在使用ATL,因此会自动完成此操作)。

7

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接