【问题标题】:Can a managed ref-class directly implement a COM interface?托管 ref 类可以直接实现 COM 接口吗?
【发布时间】:2017-06-22 02:01:24
【问题描述】:

是否有一种内置方式允许托管 ref 类实现和公开可从本机代码安全调用的 COM 接口?

在 C# 方面,这很容易通过使用适当的 COM 互操作属性装饰目标接口来完成,例如:

原生界面

interface ISampleGrabberCB: public IUnknown
{
    virtual STDMETHODIMP SampleCB( double SampleTime, IMediaSample *pSample ) = 0;
    virtual STDMETHODIMP BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen ) = 0;
}; 

static const IID IID_ISampleGrabberCB = { 0x0579154A, 0x2B53, 0x4994,
  { 0xB0, 0xD0, 0xE7, 0x73, 0x14, 0x8E, 0xFF, 0x85 } };

托管等效接口

 [Guid("0579154A-2B53-4994-B0D0-E773148EFF85")]
 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
 [SuppressUnmanagedCodeSecurity]
 public interface ISampleGrabberCB {
    int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen);
    int SampleCB(double SampleTime, IMediaSample pSample);
 } 

声明完成后,通过 P-Invoke 的魔力,您可以执行以下操作:

public class FooClass : ISampleGrabberCB {
    int ISampleGrabberCB.BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen) {
       Console.WriteLine("BufferCB called");
    }
    int ISampleGrabberCB.SampleCB(double SampleTime, IMediaSample pSample) {
       Console.WriteLine("SampleCB called");
    }

   public void SomeMethod(IBaseFilter aDirectShowFilter) {
      ISampleGrabber sampleGrabber = (ISampleGrabber)aDirectShowFilter;
      // By the magic of PInvoke, this is possible and works! 
      // ISampleGrabber->SetCallback() is expecting an ISampleGrabberCB* COM interface
      // After the following line, native code is able to callback safely
      // into our managed code
      sampleGrabber.SetCallback(this, 0);
   }
}

有没有办法在 C++/CLI 上模仿这种行为?
显然,在 C# 使用时,存在使这成为可能的互操作管道。此外,编译器可以通过检查可用的本机接口生成必要的托管接口(我仍然认为我们需要提供相关的 Guid,因为这不是本机接口中的属性)

【问题讨论】:

  • 你删除了我的评论,但它仍然像泥一样厚。我们已经知道那种代码是什么样子的,我们看不到你尝试了什么。这在 C++/CLI 中没有任何不同。 CLR 不知道您使用哪种托管语言,它适用于 MSIL。 Regasm.exe 和 Tlbexp.exe 等实用程序也没有。关键字不同,仅此而已。
  • 嗨@HansPassant,我没有删除你的评论,我收到的关于这个问题的唯一反馈是反对票。 :(
  • @HansPasant,我明白你的意思。我的问题不正确。基本上我想知道的是是否有一些可用的编译器魔法(如 gcroot)可以让我说“这个托管类实现了这个 COM 接口”,并让我提供本机 C++ 上已经可用的本机接口一方面,对我来说,这样的机制可能存在是有道理的,因为 C++/CLI 极大地简化了本机代码交互。

标签: visual-studio-2012 com c++-cli com-interop


【解决方案1】:

我只是对这个话题感到好奇并玩弄了一下,发现了一些细微的差异:

我的 PC 上有 IVI-COM 类库,并且一直想尝试与其中的一些接口,虽然 IVI 也有 .Net 接口,所以它没有太多意义......

我从 C# 开始,在那里我们获得了良好的 IntelliSense 支持。我已经添加了必要的引用并向我的项目添加了一个类。使用对象浏览器我们可以选择一个接口。

public class MyDmm : IIviDmmMultiPoint
{
}

之后只需使用 IntelliSense (Ctrl-.) 添加“using”语句,让它们为我们制作必要的属性和方法。

using Ivi.Dmm.Interop;
///...
public int Count
{
    get
    {
        throw new NotImplementedException();
    }
///...

所以现在我们需要 C++-CLI 方言 :) 如下:

using namespace IviDmmLib;
///...
public ref class Dmm : IIviDmmMultiPoint
{

注意 using 语句使用的名称不同,我们可以通过在解决方案资源管理器中选择引用并检查下面的“属性”中显示的名称来获取。

我没有完全完成实验,但我看到 COM 库是 x64 位的,所以我们可以编译相同的项目。

更多有趣的读物

如果您发现更多差异,请给我反馈,以便我们也可以将它们放在这里。

【讨论】:

  • 哇,我完全忘记了你可以导入 COM 库并让 VS 生成互操作接口这一事实!我最近做了很多 DirectShow 编程,从我遵循的示例开始,我开始手动实现它们!谢谢!!!
  • 请不要通过破坏您的帖子为他人增加工作量。通过在 Stack Exchange (SE) 网络上发帖,您已根据 CC BY-SA license 授予 SE 分发内容的不可撤销权利(即无论您未来的选择如何)。根据 SE 政策,分发非破坏版本。因此,任何破坏行为都将被撤销。请参阅:How does deleting work? …。如果允许删除,则帖子下方左侧有一个“删除”按钮,但仅在浏览器中,而不是移动应用程序中。
猜你喜欢
  • 2021-02-03
  • 2011-06-15
  • 2010-09-16
  • 2018-02-08
  • 2015-02-23
  • 2010-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多