托管的ref-class可以直接实现COM接口吗?

时间:2017-06-22 02:01:25

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

是否有内置方法允许托管引用类实现并公开可从本机代码安全地调用的COM表面?

查看C#方面,可以通过使用适当的COM-interop属性修饰目标接口来轻松完成,例如:

原生界面

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语言使用了Interop管道,使其成为可能。此外,编译器可以通过检查可用的本机接口生成必要的托管接口(我仍然认为我们需要提供相关的Guids,因为这不是本机接口中的属性)

1 个答案:

答案 0 :(得分: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位,所以我们可以为此编译项目。

更有趣的读物

如果你发现更多的差异,请给我反馈,所以我们也可以把它们放在这里。