是否可以使用反射将 COM 对象从 C# 传递到 C++?
Is It Possible To Use Reflection To Pass A COM Object From C# to C++?
我有一个 C# 程序集,它执行一些工作并将工作结果发送回 C++ 核心。我正在尝试使用反射将其传回,因为 C# 程序集运行在与它从 C++ 核心初始化的线程不同的线程上。我试过使用COM接口作为参数类型。
IDL:
HRESULT SendEvent([in] IEventData *pEventData);
C#:
WECOInspectionCoreIDL.IEventData eventData = new EventData() as WECOInspectionCoreIDL.IEventData;
var parameters = new object[1];
parameters[0] = eventData;
_piInspectionCore.GetType().InvokeMember("SendEvent", BindingFlags.InvokeMethod, null, _piInspectionCore, parameters);
这在 atlcom.h hRes = m_pInfo->Invoke(...) 调用中出现错误“0x80020005 类型不匹配”,显然最终会转换为“无法转换类型的 COM 对象” 'System.__ComObject' ...不支持这样的接口。
我也试过将参数设为 IDispatch*,然后调用转到 C++,但它似乎不是真正的对象。
IDL:
HRESULT SendEvent([in] IDispatch *pEventData);
C++:
STDMETHODIMP CInspectionCore::SendEvent(IDispatch *pEventData)
{
IEventData *pIEventData = (IEventData *)pEventData;
即使调用 pIEventData->GetIDsOfNames() 也会失败。
当从不同的 C++ 线程调用 C# 对象时,是否可以将 C# 创建的 COM 对象传递给 C++?
对于 COM,您应该永远不要像这样将一个 COM 接口转换为另一个 COM 接口:
STDMETHODIMP CInspectionCore::SendEvent(IDispatch *pEventData)
{
IEventData *pIEventData = (IEventData *)pEventData; // wrong!
}
您 必须 使用 QueryInterface,这很好用:
STDMETHODIMP CInspectionCore::SendEvent(IDispatch *pEventData)
{
IEventData* pIEventData;
HRESULT hr = pEventData->QueryInterface(&pIEventData);
if (FAILED(hr)) // etc.
}
在某些情况下(实际上经常),原始转换可能会产生这样的错误印象,即它没问题。
在您的情况下,它不起作用,因为您使用不同的线程创建隐式代理 (COM apartments, etc.)。你可以看到,如果你在 SendEvent
中设置断点,在调用时查看调用堆栈,它都是 COM 编组的东西。
我有一个 C# 程序集,它执行一些工作并将工作结果发送回 C++ 核心。我正在尝试使用反射将其传回,因为 C# 程序集运行在与它从 C++ 核心初始化的线程不同的线程上。我试过使用COM接口作为参数类型。
IDL:
HRESULT SendEvent([in] IEventData *pEventData);
C#:
WECOInspectionCoreIDL.IEventData eventData = new EventData() as WECOInspectionCoreIDL.IEventData;
var parameters = new object[1];
parameters[0] = eventData;
_piInspectionCore.GetType().InvokeMember("SendEvent", BindingFlags.InvokeMethod, null, _piInspectionCore, parameters);
这在 atlcom.h hRes = m_pInfo->Invoke(...) 调用中出现错误“0x80020005 类型不匹配”,显然最终会转换为“无法转换类型的 COM 对象” 'System.__ComObject' ...不支持这样的接口。
我也试过将参数设为 IDispatch*,然后调用转到 C++,但它似乎不是真正的对象。
IDL:
HRESULT SendEvent([in] IDispatch *pEventData);
C++:
STDMETHODIMP CInspectionCore::SendEvent(IDispatch *pEventData)
{
IEventData *pIEventData = (IEventData *)pEventData;
即使调用 pIEventData->GetIDsOfNames() 也会失败。
当从不同的 C++ 线程调用 C# 对象时,是否可以将 C# 创建的 COM 对象传递给 C++?
对于 COM,您应该永远不要像这样将一个 COM 接口转换为另一个 COM 接口:
STDMETHODIMP CInspectionCore::SendEvent(IDispatch *pEventData)
{
IEventData *pIEventData = (IEventData *)pEventData; // wrong!
}
您 必须 使用 QueryInterface,这很好用:
STDMETHODIMP CInspectionCore::SendEvent(IDispatch *pEventData)
{
IEventData* pIEventData;
HRESULT hr = pEventData->QueryInterface(&pIEventData);
if (FAILED(hr)) // etc.
}
在某些情况下(实际上经常),原始转换可能会产生这样的错误印象,即它没问题。
在您的情况下,它不起作用,因为您使用不同的线程创建隐式代理 (COM apartments, etc.)。你可以看到,如果你在 SendEvent
中设置断点,在调用时查看调用堆栈,它都是 COM 编组的东西。