我对COM有一般的了解,并希望了解COM如何帮助进行数据传输。假设有两个进程,Process-A和Process-B,并且两者都希望彼此共享一些数据,当然有很多RPC机制,但我想使用COM。
以上是我的理解,你们中的任何人都可以帮助我清楚我对这个主题的理解吗?基本上我想使用COM
在两个进程之间共享数据结构答案 0 :(得分:0)
更新:当一个对象调用另一个对象的方法(在参数中传递信息)时,我们说第一个对象向第二个对象发送消息。通常这发生在一个进程地址空间内。 COM允许一个进程中的对象在另一个进程中调用对象的方法 - 从而启用进程间通信。
COM是一个很大的话题,不可能以溢出答案的格式来解释它。我将尝试做的是在Visual Studio ATL向导的帮助下(就你在标签中提到ATL而言)演示本地进程外COM服务器和COM客户端(尽可能短)的最简单示例,它将生成大部分的代码和这提供了测试COM方法和研究样板源的可能性。但为了更好地理解,我建议在没有ATL的情况下找到inproc COM服务器实现 - 只需使用C ++。
创建结构提供程序:
在idl文件中你会有类似的东西 - 我提供这个作为检查点,所有步骤都正确完成:
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;
}

#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;
}
&#13;
因此,您有两个进程同时运行:提供对结构的访问的服务器和可以访问相同结构的客户端(您可以并行运行更多客户端进程。所有客户端访问相同的服务器进程 - 可以被视为单例 - 但每次激活都可以产生单独的进程)。客户可以更改并获取此结构的值(根据需要)。在引擎盖下,客户端可以访问自己的地址空间中的coclass代理,COM运行时支持所有进程间通信。这些代理/存根(以C / C ++源代码形式)由MIDL编译器从上面提到的接口idl文件生成。至于你专注于在两个进程之间传输数据,你应该知道有三种类型的COM封送:自定义,标准和通用。在这个例子中,通用就足够了,因为我只使用 VARIANT 兼容类型作为方法参数。要传递任意类型,您应该使用标准编组(在代理/存根dll的帮助下,在创建COM服务器的第一步中在单独的项目中生成。项目名称是带有后缀PS的服务器的项目名称)。标准封送的缺点 - 您应该使用COM服务器部署这些PS dll。
答案 1 :(得分:0)
COM exe进程外服务器特别难以编写,但Microsoft已创建COM+ Component service以简化此操作。
它包含许多服务,但是我们对Application服务感兴趣,它允许您在进程外代理主机中托管进程内服务器(DLL)。
这很简单,只需编写标准ATL DLL(或使用您喜欢的任何其他语言/框架)。我建议使用自动化类型作为接口,这样就不需要特殊的代理,例如使用如下定义的IDL接口:
interface ISharedMap : IDispatch{
[id(1)]
HRESULT PutData([in] BSTR key, [in] VARIANT value);
[id(2)]
HRESULT GetData([in] BSTR key, [out, retval] VARIANT *pValue);
};
然后创建一个新的COM +应用程序,如下所述:Creating COM+ Applications,并将其声明为服务器应用程序。这是您在完成此操作后应该看到的内容:
您的DLL现在将自动托管在特定进程(着名的dllhost.exe
)中,该进程将在客户端尝试连接时立即启动。默认情况下,相同的进程将用于各种进程外COM客户端。它会在一段时间后关闭,但您可以通过各种方式配置COM +应用程序,例如使用'空闲时保持运行'标志设置':
现在,您将能够为所有您喜欢的COM客户端使用跨进程内存缓存,例如,通过简单的javascript .js代码:
var map = new ActiveXObject("SharedMap");
map.PutData("mykey", "mydata")
var data = map.GetData("mykey")
注意:缓存的实现留给读者,但它可以重用另一个COM +服务:COM+ Shared Property Manager