托管 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 位的,所以我们可以为相同的项目编译。
更多有趣的读物:
如果您发现更多差异,请给我反馈,我们也可以把它们放在这里。
是否有内置方法允许托管 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 位的,所以我们可以为相同的项目编译。
更多有趣的读物:
如果您发现更多差异,请给我反馈,我们也可以把它们放在这里。