免注册类COM互操作和线程 [英] Registration-free COM-like interop and threading
问题描述
我正在使用具有WPF GUI和不受管理的C ++后端的桌面应用程序. 我已经通过以下方式定义了API(C#版本,已截断):
I’m working on a desktop app that has WPF GUI and unmanaged C++ backend. I’ve defined API the following way (C# version, truncated):
[Guid( "###" ), InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]
interface iMyApp
{
void aMethod();
}
[DllImport( "my.dll", PreserveSig = true )]
public extern static int create( string configPath, out iMyApp a );
在后端我有
__interface __declspec( uuid( "###" ) ) iMyApp: public IUnknown
{
HRESULT __stdcall aMethod();
}
和基于ATL的经典实现.
And classic ATL-based implementation.
这很好且快速,不需要COM注册,没有类型库,没有MIDL编译器等.
This works nice and fast, requires no COM registration, no type libraries, no MIDL compiler, etc.
问题是,我无法在C#中跨线程传递iMyApp实例,所以引发了E_NOINTERFACE异常.
The problem is, I can’t pass iMyApp instances across threads in C#, E_NOINTERFACE exception is raised.
我的实现与线程无关.
如何告诉.NET以使其停止在线程间编组接口,而在所有线程上使用相同的IUnknown指针?如果有问题,我只需要支持4.5 +
How to tell that to .NET so it stops marshalling my interfaces across threads, and just use the same IUnknown pointer on all threads? If it matters, I only need to support 4.5+
推荐答案
正如汉斯·帕桑特(Hans Passant)所暗示的那样,此处的键是
As hinted by Hans Passant, the key here is CoCreateFreeThreadedMarshaler API.
添加私有变量CComPtr<IUnknown> m_ftm;
初始化该编组:
HRESULT FinalConstruct()
{
IUnknown* pUnk = GetUnknown();
return CoCreateFreeThreadedMarshaler( pUnk, &m_ftm );
}
通过将以下行添加到接口映射中,在QueryInterface中处理IID_IMarshal:
Process IID_IMarshal in QueryInterface, by adding the following line to the interface map:
COM_INTERFACE_ENTRY_AGGREGATE( IID_IMarshal, m_ftm )
在那之后,C#代码将愉快地从任何线程调用那些对象.当然,您必须自己处理同步, CComAutoCriticalSection /<一个href ="https://msdn.microsoft.com/zh-cn/library/33ydddb1.aspx" rel ="nofollow noreferrer"> CComCritSecLock 通常会有所帮助.
After that, C# code will happily call those objects from any thread. Of course you'll have to handle synchronization yourself, CComAutoCriticalSection / CComCritSecLock often help.
更新:MS在VS 2017中破解了我的代码,更新了答案.查看VS2015版本的编辑历史记录.
Update: MS broke my code in VS 2017, updated the answer. See edit history for VS2015 version.
这篇关于免注册类COM互操作和线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!