【发布时间】: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