从WRL COM组件获取托管回调

时间:2014-05-09 06:14:21

标签: c# c++ com delegates windows-runtime

背景(或者,看看我走了多远!)

我从Windows 8 Media Extension Sample开始。我正在使用灰度示例作为起点来学习如何将值从托管代码传递到COM对象,以及如何将值从COM对象传递回托管代码。在我的IDL文件中,我有一个GrayscaleEffect类(完全取自示例)和一个自定义接口,可以让我在c#世界中查询字符串。

IDL文件:

namespace GrayscaleTransform
{
    [version(NTDDI_WIN8), uuid(553B5684-4C22-4D21-8638-1E7D86D84F10)]
    interface MyInterface : IInspectable {
        HRESULT GetMsg([out] HSTRING *message);
    }

    [version(NTDDI_WIN8)]
    runtimeclass GrayscaleEffect {
        interface Windows.Media.IMediaExtension;
        interface MyInterface;
    }
}

我的GrayscaleEffect类实现实现了GetMsg以返回字符串“Woozle”

相关的c#:

cap = new MediaCapture();
await cap.InitializeAsync();

previewElement1.Source = cap;
await cap.StartPreviewAsync();

PropertySet props = new PropertySet();
await cap.AddEffectAsync(
    Windows.Media.Capture.MediaStreamType.VideoPreview,
    "GrayscaleTransform.GrayscaleEffect",
    props);

if (this.props.ContainsKey("ref"))
{
    var augGui = (GrayscaleTransform.MyInterface)this.props["ref"];
    string message;
    augGui.GetMsg(out message);
}

在调用GetMsg之后,我可以看到该消息包含字符串“Woozle”,就像我期望的那样 - 非常好!

问题

现在我想做一些有点发烧友的事情。我想要实现一个允许我将代理从C#传递给COM的方法,而不是让我将字符串从COM传递给C#的方法。我想让MFT课程每10个视频帧或其他东西调用这个方法 - 这部分并不重要。我希望我的接口有一个名为SubscribeEvent的方法,它将一个委托作为参数。现在,它可以是一个不带参数的void委托。

This page让我相信我应该能够在COM世界中声明一个WinRT委托,并且能够从C#传递相同类型的委托(参见最后的第3个项目)。酷 - 看起来很容易。到目前为止,我最好的尝试在idl中是这样的:

delegate void CallbackMethod();

[version(NTDDI_WIN8), uuid(553B5684-4C22-4D21-8638-1E7D86D84F10)]
interface MyInterface : IInspectable {
    HRESULT Subscribe(CallbackMethod cb);
}

不幸的是,这会导致错误 - 似乎与委托CallbackMethod的声明有关:

错误MIDL9008:内部编译器问题 - 有关如何查找变通方法的建议,请参阅文档。

修改 这一点很明显。该语法是C ++ / cx的东西。经过仔细检查,我没有打开C ++ / CX扩展。这是一个WRL项目,这意味着它具有模板魔术的常规风格c ++。

我还尝试通过实现IConnectionPoint接口来连接事件,但是当我包含OCIdl.h时,我得到一个编译错误,即无法为ARM编译桌面组件。

问题 我在这里吠叫错了吗?我应该使用C ++ / CX使我的GrayscaleEffect类成为WinRT运行时类吗?也许我们冒险进入“新问题”领域,但是当我尝试用C ++ / CX中的WinRT类实现IMFTransform时,我得到了

错误C2811:'GrayscaleRT :: Class1':不能从'IMFTransform'继承,ref类只能从ref类或接口类继承

更好的问题: 怎么样:我可以在这里通过代表吗?如果只有我知道WRL模板的神奇组合才能使它工作,我就像我应该能够一样。

1 个答案:

答案 0 :(得分:0)

看起来像this is the answer。在WRL中,您在idl中声明一个事件,如下所示:

[uuid(3FBED04F-EFA7-4D92-B04D-59BD8B1B055E), version(NTDDI_WIN8)]
delegate HRESULT WhateverEvent();

参见添加在计算素数时触发的事件部分

我的问题是我最初不明白我不是使用c ++ / cx。我使用常规c ++和WRL,这是一个类似于ATL的模板库,它使WinRT编程更容易,并且不使用非标准语言扩展。

一旦我明白了,使用WRL

找到一个事件处理程序的例子相对容易