如何使用 COM 在两个进程之间传输数据(对于 IPC - 进程间通信) [英] How to use COM to transfer Data between two processes (for IPC - inter process communication)

查看:30
本文介绍了如何使用 COM 在两个进程之间传输数据(对于 IPC - 进程间通信)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

i have a average knowledge in COM and will like to understand how COM helps in data transfer. Assuming there are two processes, Process-A and Process-B and both of them wants share some data with each other, of course there are many RPC mechanisms but i would like to use COM.

  1. 您不能创建 COM dll,因为那样它会变得特定于进程并且无法使用
  2. 我们能否创建一个单吨 COM EXE 服务器并将结构包装在 COM CoClass 中并将其成员公开为属性,然后......不知道该怎么做?

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

Above is my understanding, can anyone of you help me clear my understanding on this topic? basically i would like to share a data structure between two process using COM

推荐答案

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

Updated: when one object call method of another object (passing information in parameters) we say that first object sends message to second one. Usually this happen s within one process address space. COM allows object in one process to call method of object in another process - thus enabling interprocess communication.

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

COM is huge topic and it is not possible to explain it in format of overflow answer. What I will try to do is to demonstrate simplest example of local out of process COM server and COM client (as short as possible) with help of Visual Studio ATL wizards(as far as you mentioned ATL in tags) that will generate most of the code and this gives the possibility to test COM approach and investigate boilerplate sources. But for better understanding I recommend to find inproc COM server implementation without ATL - just with C++.

  1. 创建结构提供者:

  1. Creating Structure provider:

  • 创建名为 COMStructProvider 的新 ATL 项目(在 Visual C++ 中选择 ATL 项目模板).在向导中选择可执行"应用程序类型(不是 DLL).默认为其他选项.向导将生成项目文件.
  • 选择项目 -> 添加类 -> ATL 简单对象 -> 添加.简而言之,名称字段类型为任意名称,例如 MyStruct.点击完成".这将为 MyStruct coclass 添加头文件和实现文件.还将添加 MyStruct.rgs 以帮助在注册表中注册您的 coclass.现在您拥有最小的 COM 服务器并且可以构建解决方案,但要做到这一点,您需要以管理员身份运行 VS(因为它将在注册表中注册您的服务器),否则注册失败.
  • 在 CMyStruct(VS prepend class with C default) 类中添加两个数据成员:私人的:std::string m_name;int m_age;
  • 在前面的步骤中,向导创建了 IMyStruct 接口(您可以在 idl 文件中看到它).现在我们要向这个接口添加方法:我们的两个私有数据成员的 getter 和 setter.选择 Class View 选项卡,选择 IMyStruct 接口(派生自 IDispatch),在上下文菜单中选择添加方法".例如方法名称 getAge 带有参数 LONG*、参数属性out"和参数名称:age(单击添加以添加参数).这为 idl 文件以及 header 和 impl 文件添加了新方法.重复为 setAge(在 LONG 类型的参数中)、getName(out,BSTR*)、setName(in,BSTR)添加方法.参数名称无关紧要.

在 idl 文件中,您将拥有类似的内容 - 我将其作为检查点,以确保所有步骤都正确完成:

In idl file you will have something like that - I provide this as checkpoint that all steps are done correctly:

import "oaidl.idl";
import "ocidl.idl";

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

  • 添加实现:
  • STDMETHODIMP CMyStruct::getAge(LONG* age)
    {
    	*age = m_age;
    	return S_OK;
    }
    
    
    STDMETHODIMP CMyStruct::setAge(LONG age)
    {
    	m_age = age;
    	return S_OK;
    }
    
    
    STDMETHODIMP CMyStruct::getName(BSTR* name)
    {
    	*name = SysAllocString(m_name.c_str());
    	return S_OK;
    }
    
    
    STDMETHODIMP CMyStruct::setName(BSTR name)
    {
    	m_name.assign(name);
    	return S_OK;
    }

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

    #include <iostream>
    // check for correct path to tlb library. Will create tlh, tli files that provide smart pointers, etc.
    #import "..\COMStructProvider\Debug\COMStructProvider.tlb" no_namespace named_guid
    
    using namespace std;
    
    int main()
    {
        // initialize COM runtime
    	CoInitialize(NULL);
    	{
            // smart pointer simplifies work, will invoke CoCreateInstance to activate COM server
    		IMyStructPtr spMyStruct(__uuidof(MyStruct));
    		BSTR name = SysAllocString(L"John");
    		spMyStruct->setName(name);
    		SysFreeString(name);
    
    		BSTR retreivedName;
    		spMyStruct->getName(&retreivedName);
    		wcout << "name " << retreivedName << endl;
    		SysFreeString(retreivedName);
    
    		spMyStruct->setAge(5);
    
    		long age = 0;
    		spMyStruct->getAge(&age);
    
    		cout << "age " << age << endl;
    	}
    	CoUninitialize();
    
    	return 0;
    }

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

    So, you have two processes running simultaneously: server that provides access to structure and client that has access to the same structure (you can run more client processes in parallel. All clients access the same server process - can be considered as singleton - but it's possible to spawn separate process with each activation). Client can change and get values of this structure (as was required). Under the hood client has access to proxy of coclass in its own address space and COM runtime support all interprocess communication. Those proxy/stubs (in the form of C/C++ sources) are generated by MIDL compiler from interface idl file mentioned above. As far as you focused on transfering Data between two process you should know that there are three types of COM marshaling: custom, standard and universal. In this example universal is sufficient because I use only VARIANT compatible types as method parameters. To pass arbitrary types you should use standard marshaling (with help of proxy/stub dlls, generated in separate project on first step when creating COM server. name of project is the name of project with server with suffix PS). Disadvantage of standard marshaling - you should deploy those PS dlls with your COM server.

    这篇关于如何使用 COM 在两个进程之间传输数据(对于 IPC - 进程间通信)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆