2013-10-31 49 views
1

我已經創建了一個採用雙指針(BYTE **)的COM方法。在COM內部,我正在分配內存並初始化它。如何將C#中的雙指針傳遞給COM並在COM中初始化它

簽名是;

HRESULT Canny([in] BSTR szLogoPath, [out] BYTE** pBuffer, [out] USHORT* iBufLen); 

問題是當我從C#項目調用它時COM崩潰,而當我從WIN32項目調用它時它工作正常。

另外,在C#項目中上面的方法顯示爲; (BYTE **被顯示爲IntPtr的)

public virtual void Canny(string szLogoPath,IntPtr pBuffer, out ushort iBufLen); 

我的C#代碼是

LogoFinderClass libCOM = new LogoFinderClass(); 
unsafe { 
    byte* buf = null; 
    IntPtr interopPtr = new IntPtr(&buf); 
    libCOM.Canny(@"..\Logo.bmp", interopPtr, out bufLen); 
} 

在C++中,我作爲分配存儲器;

::Canny(BSTR szLogoPath, BYTE** pBuffer, USHORT* iBufLen) { 
    *pBuffer = new BYTE[1024]; 
    .. 
} 

而當從C#調用時,COM分配內存時崩潰。

+0

在COM互操作中使用* new *運算符總是錯誤的。客戶端代碼無法調用正確的* delete *操作符,因此需要CoTaskMemAlloc。如果它很快崩潰,那麼你可能會損壞堆。對於像Canny這樣的圖像處理操作,1024字節聽起來方式太低。 –

+0

謝謝@HansPassant,我現在使用CoTaskMemAlloc(),它工作正常,但Marshal.Copy(..)不是複製我分配在COM內的字節數,就像我分配8000字節,但它正在複製大約5000字節,我認爲IntPtr正在破壞某處。 **是1024是兩個低的canny操作我剛剛提到它作爲虛擬值** –

回答

3

這裏不需要unsafe。您確實需要在C#端更改函數的聲明。 buffer參數需要被聲明爲:

ref IntPtr pBuffer 

然後,一旦你調用的函數,讀出緩衝與Marshal.Copy內容。

我不是從C#消費COM的導出,但不應該第一個參數有[MarshalAs(UnmanagedType.BStr)]

另外,如果您使用CoTaskMemAlloc而不是new,則可以讓調用方取消分配緩衝區,而不必導出釋放程序。我相信你確實導出了一個釋放器?

+0

感謝@大衛的答覆。 請你能告訴我如何在C#端編輯函數聲明,因爲解決方案資源管理器中的引用過濾器下的lib(COM)不會公開任何屬性來編輯它的簽名。 –

+0

@SKAR正如我所說的,我不熟悉C#中的COM。所以,我不知道VS中的具體情況。抱歉。但肯定必須有C#源代碼聲明接口? –

+0

謝謝@David,當使用CoTaskMemAlloc(..)分配內存時,COM不會崩潰,但Marshal.Copy(..)不會複製我在COM中分配的字節數,就像我分配8000字節,但它正在複製大約5000字節,我認爲IntPtr正在破壞某個地方。但是,當從WIN32調用時它仍然工作正常:( –