如何使用COM在两个进程之间传输数据

use*_*801 6 com atl visual-c++

我对COM有一般的了解,并希望了解COM如何帮助进行数据传输.假设有两个进程,Process-A和Process-B,它们都希望彼此共享一些数据,当然有很多RPC机制,但我想使用COM.

  1. 您无法创建COM dll,因为它将变得特定于进程并且无法使用
  2. 我们可以创建一个单吨COM EXE服务器并将结构包装在COM CoClass中并将其作为属性公开,然后......不知道如何操作?

以上是我的理解,你们中的任何人都可以帮助我清楚我对这个主题的理解吗?基本上我想在使用COM的两个进程之间共享一个数据结构

Kap*_*nir 1

更新:当一个对象调用另一个对象的方法(在参数中传递信息)时,我们说第一个对象向第二个对象发送消息。通常这种情况发生在一个进程地址空间内。COM 允许一个进程中的对象调用另一进程中对象的方法 - 从而实现进程间通信。

\n\n

COM是一个很大的话题,不可能以溢出答案的形式解释它。我将尝试做的是在 Visual Studio ATL 向导(就您在标签中提到的 ATL 而言)的帮助下演示本地进程外 COM 服务器和 COM 客户端(尽可能短)的最简单示例,该向导将生成大部分代码,这使得测试 COM 方法和调查样板源成为可能。但为了更好地理解,我建议找到不带 ATL 的 inproc COM 服务器实现 - 仅使用 C++。

\n\n
    \n
  1. 创建结构提供者:

    \n\n
      \n
    • 创建名为 COMStructProvider 的新 ATL 项目(在 Visual C++ 中选择 ATL 项目模板)。在向导中选择 \xe2\x80\x9cExecutable\xe2\x80\x9d 应用程序类型(不是 DLL)。其他选项默认即可。向导将生成项目文件。
    • \n
    • 选择项目 -> 添加类 -> ATL 简单对象 -> 添加。在短名称字段中键入任意名称,例如 MyStruct。单击\xe2\x80\x9c完成\xe2\x80\x9d。这将为 MyStruct coclass 添加头文件和实现文件。此外,还将添加 MyStruct.rgs 以帮助在注册表中注册您的组件类。现在你已经有了最小的COM服务器并且可以构建解决方案,但是要做到这一点,你需要以管理员身份运行VS(因为它将在注册表中注册你的服务器),否则注册会失败。
    • \n
    • 向 CMyStruct 添加两个数据成员(VS 默认在类前面加上 C) class:\nprivate:\nstd::string m_name;\nint m_age;
    • \n
    • 在前面的步骤中,向导创建了接口 IMyStruct(您可以在 idl 文件中看到它)。现在我们要向该接口添加方法:向我们的两个私有数据成员添加 getter 和 setter。选择“类视图”选项卡,选择 IMyStruct 接口(派生自 IDispatch),在上下文菜单中选择 \xe2\x80\x9cadd 方法\xe2\x80\x9d。例如,方法名称为 getAge,参数为 LONG*,参数属性为 \xe2\x80\x9cout\xe2\x80\x9d,参数名称为:age(单击“添加”以添加参数)。这会向 idl 文件以及头文件和 impl 文件添加新方法。重复添加 setAge(在 LONG 类型的参数中)、getName (out, BSTR* )、setName(in, BSTR) 方法。参数名称\xe2\x80\x99 并不重要。
    • \n
  2. \n
\n\n

在 idl 文件中,您将看到类似的内容 - 我提供此作为所有步骤均正确完成的检查点:

\n\n
import "oaidl.idl";\nimport "ocidl.idl";\n\n[\n    object,\n    uuid(AA2DA48C-CD1E-4479-83D4-4E61A5F188CB),\n    dual,\n    nonextensible,\n    pointer_default(unique)\n]\ninterface IMyStruct : IDispatch{\n    [id(1)] HRESULT getAge([out] LONG* age);\n    [id(2)] HRESULT setAge([in] LONG age);\n    [id(3)] HRESULT getName([out] BSTR* name);\n    [id(4)] HRESULT setName([in] BSTR name);\n};\n[\n    uuid(E7A47886-D580-4853-80AE-F10FC69E8D73),\n    version(1.0),\n]\nlibrary COMStructProviderLib\n{\n    importlib("stdole2.tlb");\n    [\n        uuid(CC51EFFE-C8F4-40FA-AEA3-EB6D1D89926E)      \n    ]\n    coclass MyStruct\n    {\n        [default] interface IMyStruct;\n    };\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n
    \n
  • 添加实现:
  • \n
\n\n

\r\n
\r\n
import "oaidl.idl";\nimport "ocidl.idl";\n\n[\n    object,\n    uuid(AA2DA48C-CD1E-4479-83D4-4E61A5F188CB),\n    dual,\n    nonextensible,\n    pointer_default(unique)\n]\ninterface IMyStruct : IDispatch{\n    [id(1)] HRESULT getAge([out] LONG* age);\n    [id(2)] HRESULT setAge([in] LONG age);\n    [id(3)] HRESULT getName([out] BSTR* name);\n    [id(4)] HRESULT setName([in] BSTR name);\n};\n[\n    uuid(E7A47886-D580-4853-80AE-F10FC69E8D73),\n    version(1.0),\n]\nlibrary COMStructProviderLib\n{\n    importlib("stdole2.tlb");\n    [\n        uuid(CC51EFFE-C8F4-40FA-AEA3-EB6D1D89926E)      \n    ]\n    coclass MyStruct\n    {\n        [default] interface IMyStruct;\n    };\n};\n
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

    \n
  1. 创建客户端。将新的 Win32 控制台应用程序项目 MyStructClient 添加到解决方案(可执行文件)。添加以下代码:
  2. \n
\n\n

\r\n
\r\n
STDMETHODIMP CMyStruct::getAge(LONG* age)\r\n{\r\n\t*age = m_age;\r\n\treturn S_OK;\r\n}\r\n\r\n\r\nSTDMETHODIMP CMyStruct::setAge(LONG age)\r\n{\r\n\tm_age = age;\r\n\treturn S_OK;\r\n}\r\n\r\n\r\nSTDMETHODIMP CMyStruct::getName(BSTR* name)\r\n{\r\n\t*name = SysAllocString(m_name.c_str());\r\n\treturn S_OK;\r\n}\r\n\r\n\r\nSTDMETHODIMP CMyStruct::setName(BSTR name)\r\n{\r\n\tm_name.assign(name);\r\n\treturn S_OK;\r\n}
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

因此,您有两个进程同时运行:提供对结构的访问的服务器和可以访问相同结构的客户端(您可以并行运行更多客户端进程。所有客户端访问相同的服务器进程 - 可以被视为单例 - 但它每次激活都可以产生单独的进程)。客户端可以更改并获取此结构的值(根据需要)。在底层,客户端可以访问其自己的地址空间中的 coclass 代理,并且 COM 运行时支持所有进程间通信。这些代理/存根(以 C/C++ 源代码的形式)是由 MIDL 编译器从上面提到的接口 idl 文件生成的。如果您专注于在两个进程之间传输数据,您应该知道 COM 封送处理分为三种类型:自定义、标准和通用。在此示例中,通用就足够了,因为我仅使用VARIANT兼容类型作为方法参数。要传递任意类型,您应该使用标准封送处理(在代理/存根 dll 的帮助下,在创建 COM 服务器时在第一步中在单独的项目中生成。项目名称是带有后缀 PS 的服务器的项目名称)。标准封送处理的缺点 - 您应该使用 COM 服务器部署这些 PS dll。

\n

  • 您需要创建一个 COM exe 服务器而不是 DLL 并创建 CoClass Singleton,现在您想要交换数据的两个进程可以实例化 COM 类并设置一些属性,而另一个进程可以获取这些属性 (2认同)