簡體   English   中英

在C#中使用C ++回調接口

[英]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方法永遠不會被調用。 該視頻記錄沒有問題,只是回調根本沒有執行。

我做互操作的方式有問題嗎?

我通常與不安全的C#代碼中的函數指針的委托一起工作。
唯一的技巧是,您需要確保不會對該委托的引用進行垃圾收集,因為在對垃圾收集器中的引用進行計數時,將不使用不安全代碼中的引用。 因此,該功能要么需要是靜態的,要么是持有引用的對象需要附加的人工引用以確保其可用性。
這是在MSDN上使用委托教程

您進行互操作的方式看起來很好。 我看了看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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM