[英]How to implement COM callback interface in C++, from C# assembly, using `#import` and `tlb` file?
[英]Using a C++ callback interface in C#
我正在编写一个需要使用DirectShow录制视频的应用程序-为此,我正在使用Interop库DirectShowLib,它看起来很棒。
但是,由于样本已写入文件中,因此现在我需要获取回调通知,因此可以添加数据单元扩展。 根据msdn文档,在C ++中,这是通过实现IAMWMBufferPassCallback接口并将结果对象传递到引脚的IAMWMBufferPass接口的SetNotify方法来完成的。
因此,我创建了一个小类,该类从DirectShowLib实现IAMWMBufferPassCallback接口:
class IAMWMBufferPassCallbackImpl : IAMWMBufferPassCallback
{
private RecordingPlayer player;
public IAMWMBufferPassCallbackImpl(RecordingPlayer player)
{
this.player = player;
}
public int Notify(INSSBuffer3 pNSSBuffer3, IPin pPin, long prtStart, long prtEnd)
{
if (player.bufferPin == pPin && !player.firstBufferHandled)
{
player.firstBufferHandled = true;
//do stuff with the buffer....
}
return 0;
}
}
然后,我检索了所需引脚的IAMWMBufferPass接口,并将该类的实例传递给SetNotify方法:
bufferPassCallbackInterface = new IAMWMBufferPassCallbackImpl(this);
IAMWMBufferPass bPass = (IAMWMBufferPass)DSHelper.GetPin(pWMASFWriter, "Video Input 01");
hr = bPass.SetNotify(bufferPassCallbackInterface);
DsError.ThrowExceptionForHR(hr);
没有引发异常,表明SetNotify方法成功。
现在的问题是,我的回调对象中的Notify方法永远不会被调用。 该视频记录没有问题,只是回调根本没有执行。
我做互操作的方式有问题吗?
您进行互操作的方式看起来很好。 我看了看MSDN文档,看起来您也朝着正确的方向前进,所以我不知道为什么它不进行回调。
但是,一旦完成回调,您可能需要确保调用Marshal.ReleaseComObject(pNSSBuffer3)。 有时,直到所有其他引用都被删除后,样本缓冲区才会释放出来进行处理。 SampleGrabber就是这种情况,因此可能与此相同。
您可能应该使用委托:
delegate int NotifyDelegate(INSSBuffer3 pNSSBuffer3, IPin pPin, long prtStart, long prtEnd);
void run(){
bufferPassCallbackInterface = new IAMWMBufferPassCallbackImpl(this);
IAMWMBufferPass bPass = (IAMWMBufferPass)DSHelper.GetPin(pWMASFWriter, "Video Input 01");
NotifyDelegate d = new NotifyDelegate(bufferPassCallbackInterface.Notify);
hr = bPass.SetNotify(d);
DsError.ThrowExceptionForHR(hr);
}
但是,我不太确定如何在托管类上实现非托管接口。 C ++中的INSSBuffer3 *与C#中的新INNSBuffer3()不直接相关。
为了回应您的评论,SetNotify函数定义为
HRESULT SetNotify(
[in] IAMWMBufferPassCallback *pCallback
);
因此,它需要一个指向IAMWMBufferPassCallback的实现的指针。
MSDN说pCallback是pCallback a
指向应用程序的IAMWMBufferPassCallback接口的指针。
委托是(试图成为)托管的等效于IAMWMBufferPassCallback的指针。 回调通常是一种方法,而不是对象。 因此,传递委托的实例将为您工作。 另一个类似的示例是InternetSetStatusCallback ,您可以在其中传递指向InternetStatusCallback的实现的指针。
我会尝试一下,如果它不起作用,为什么不尝试一个已经有人完成所有辛苦工作的图书馆呢? DirectShowNet可能是一个选项(我从未使用过)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.