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

C++ 我的$Foo ATL解决方案中的($Foo)PS项目用于什么?,c++,visual-studio,com,atl,C++,Visual Studio,Com,Atl,在MSVC中创建ATL项目似乎不是创建一个而是创建两个项目;后者的名称与前者相同,但名称后面附加了PS。第二个项目的目的是什么?如何判断我是否需要它?它是代理/存根代码,其中包含在不同单元之间传输数据所需的非标准数据封送器(线程相关)。当调用您的COM对象的应用程序使用不同的COM线程模型时,将使用它。ATL/COM向导中有一个选项可以将此代码合并到主库中。在许多常见场景中,您不必担心它(即当您的COM dll在客户端上下文中运行时),除非您想编写自定义封送拆收器。正如@ebutusov所说,*

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

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

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

如果在*.IDL文件中未定义任何自定义接口,或者仅定义具有双和双自动修改器的接口,则可以从解决方案中删除PS project。在这种情况下,将使用标准的typelib封送拆收器


为了能够使用标准的typelib封送拆收器,必须注册typelibrary(这是在使用ATL时自动完成的)

COM支持跨两个不同的线程、两个不同的进程或两台不同的机器进行接口方法调用。这叫做封送。两个不同的线程是最常见的情况,COM服务器通常不是线程安全的。COM通过封送从“错误”线程到创建服务器的线程的调用,为此类单线程类实现线程安全。在写入进程外服务器时,会在进程之间进行封送处理。网络上不同机器之间的通信称为DCOM

这是通过创建与原始接口完全相同的接口实例来实现的。但该接口的所有方法实际上都是执行封送调用工作的替代方法。这是代理。在电线的另一端,有一个替代品,看起来与接口完全一样,但做的是相反的工作。这是存根。代理和存根一起工作会产生一种错觉,即您正在程序中进行一个简单的方法调用

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


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

“PS”代表代理/存根,可能有人比我更了解它的含义!Visual Studio 2017向导包含一个复选框“允许合并代理/存根代码”,该复选框阻止创建PS项目。答案。。。让我开心:)