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

Can a managed ref-class directly implement a COM interface?

是否有内置方法允许托管 ref-class 实现和公开可从本机代码安全调用的 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,因为这不是本机接口中的属性)

我只是对这个话题很好奇,玩了一下,发现了一些细微的差别:

我的 PC 上有 IVI-COM class 库,并且一直想尝试连接其中的一些,尽管 IVI 也有 .Net 接口,所以它没有太大意义......

我从 C# 开始,我们在其中获得了良好的 IntelliSense 支持。我已经添加了必要的引用并向我的项目添加了 class。使用对象浏览器,我们可以 select 一个界面。

public class MyDmm : IIviDmmMultiPoint
{
}

之后只需使用智能感知(Ctrl-.)添加'using'语句,让他们为我们制作必要的属性和方法。

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

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

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

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

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

更多有趣的读物:

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