进行异步 COM 调用——我必须创建自己的 P/S 吗?
Making an async COM call -- do I have to create my own P/S?
我有一个在类型库中定义并在我的代码中实现的自定义接口。我还没有创建自己的 proxy/stub。我已经成功地将接口指针从我的主线程 (STA) 编组到后台线程 (STA),在我的例子中使用 IGlobalInterfaceTable.
我想从那个后台线程对 UI 线程上的对象进行异步调用。我还没有实现 ICallFactory in my object. I see that the standard proxy does indeed implement ICallFactory (i.e, I can successfully QI on the background thread for ICallFactory). But the CreateCall,因为我的自定义接口因 HRESULT 0x80040150 而失败(无法从注册表中读取密钥)。
我是否需要创建自己的明确实现 ICallFactory 的代理才能执行此操作?
这是我的 IDL:
[
object,
uuid(92303FE7-A79D-47DD-923F-62062105C00E),
async_uuid(2880C40C-9965-4544-AE39-DF08056E8CB6),
nonextensible,
pointer_default(unique),
oleautomation
]
interface IFoo: IUnknown
{
HRESULT Foo([in] long a, [in] long b);
}
[
uuid(D58B0A31-A2D5-4BFB-8702-3B710320493B)
]
coclass Foo
{
[default] interface IFoo;
};
这是我单元测试中的后台线程过程:
static DWORD WINAPI threadproc(LPVOID lpParameter)
{
// get arguments
DWORD cookie = *(DWORD*)lpParameter;
// initialize COM
Assert::AreEqual(S_OK, CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
{
// get global interface table
IGlobalInterfaceTablePtr globalInterfaceTable;
Assert::AreEqual(S_OK, globalInterfaceTable.CreateInstance(CLSID_StdGlobalInterfaceTable));
// get object
MyLib::IFooPtr object;
Assert::AreEqual(S_OK, globalInterfaceTable->GetInterfaceFromGlobal(cookie, MyLib::IID_IFoo, (LPVOID*)&object));
// get async call factory
ICallFactoryPtr callFactory;
Assert::AreEqual(S_OK, object->QueryInterface(&callFactory));
//
// Everything is fine up until the CreateCall call below,
// which fails with HRESULT 0x80040150
//
// create async call object
IUnknownPtr callObject;
Assert::AreEqual(S_OK, callFactory->CreateCall(MyLib::IID_AsyncIFoo, NULL, IID_IUnknown, &callObject));
}
// uninitialize COM
CoUninitialize();
// success
return 0;
}
据我所知,通用编组器不适用于 Async COM。您需要构建(MIDL 生成的)代理(尽管 IIRC,如果您正在构建 DLL,则可以合并存根)。
您还需要注册代理 DLL(并使用 -DREGISTER_PROXY_DLL 定义构建它)。 Async COM 需要定义更多注册表项才能使其正常工作。
我有一个在类型库中定义并在我的代码中实现的自定义接口。我还没有创建自己的 proxy/stub。我已经成功地将接口指针从我的主线程 (STA) 编组到后台线程 (STA),在我的例子中使用 IGlobalInterfaceTable.
我想从那个后台线程对 UI 线程上的对象进行异步调用。我还没有实现 ICallFactory in my object. I see that the standard proxy does indeed implement ICallFactory (i.e, I can successfully QI on the background thread for ICallFactory). But the CreateCall,因为我的自定义接口因 HRESULT 0x80040150 而失败(无法从注册表中读取密钥)。
我是否需要创建自己的明确实现 ICallFactory 的代理才能执行此操作?
这是我的 IDL:
[
object,
uuid(92303FE7-A79D-47DD-923F-62062105C00E),
async_uuid(2880C40C-9965-4544-AE39-DF08056E8CB6),
nonextensible,
pointer_default(unique),
oleautomation
]
interface IFoo: IUnknown
{
HRESULT Foo([in] long a, [in] long b);
}
[
uuid(D58B0A31-A2D5-4BFB-8702-3B710320493B)
]
coclass Foo
{
[default] interface IFoo;
};
这是我单元测试中的后台线程过程:
static DWORD WINAPI threadproc(LPVOID lpParameter)
{
// get arguments
DWORD cookie = *(DWORD*)lpParameter;
// initialize COM
Assert::AreEqual(S_OK, CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
{
// get global interface table
IGlobalInterfaceTablePtr globalInterfaceTable;
Assert::AreEqual(S_OK, globalInterfaceTable.CreateInstance(CLSID_StdGlobalInterfaceTable));
// get object
MyLib::IFooPtr object;
Assert::AreEqual(S_OK, globalInterfaceTable->GetInterfaceFromGlobal(cookie, MyLib::IID_IFoo, (LPVOID*)&object));
// get async call factory
ICallFactoryPtr callFactory;
Assert::AreEqual(S_OK, object->QueryInterface(&callFactory));
//
// Everything is fine up until the CreateCall call below,
// which fails with HRESULT 0x80040150
//
// create async call object
IUnknownPtr callObject;
Assert::AreEqual(S_OK, callFactory->CreateCall(MyLib::IID_AsyncIFoo, NULL, IID_IUnknown, &callObject));
}
// uninitialize COM
CoUninitialize();
// success
return 0;
}
据我所知,通用编组器不适用于 Async COM。您需要构建(MIDL 生成的)代理(尽管 IIRC,如果您正在构建 DLL,则可以合并存根)。
您还需要注册代理 DLL(并使用 -DREGISTER_PROXY_DLL 定义构建它)。 Async COM 需要定义更多注册表项才能使其正常工作。