免注册类COM互操作和线程 [英] Registration-free COM-like interop and threading

查看:94
本文介绍了免注册类COM互操作和线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用具有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屋!

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