2017-08-17 36 views
-1

這是我試圖調用的方法簽名。努力從本地DLL調用方法使用C#

EXTERN_C 
HRESULT 
QueryData(
    _Outptr_opt_result_bytebuffer_(*SizeOfData) PBYTE * Data, 
    _Out_opt_         UINT32* SizeOfData, 
    _In_          BOOL IsDataType 
) 

上述方法是不是我的代碼,它的供應商代碼,不幸的是我沒有足夠的知識,如何調用此方法。我所知道的是它是想讓我獲得一塊數據。

這是我迄今爲止所做的。

[DllImport("DataGetter.dll")] 
     internal static extern int QueryData(IntPtr data, UIntPtr sizeOfData, bool isDataType); 

IntPtr data= new IntPtr(); 
      UIntPtr sizeOfData= new UIntPtr(); 
      bool isDataType= true; 
      int hresult = QueryData(data, sizeOfData, isDataType); 

我的方法不失敗,但它並沒有在數據返回任何東西。任何想法如何從C#調用這個奇怪的方法?

+0

你嘗試過調用任何更簡單的函數嗎?或者明確地設置調用約定? '[DllImport(「DataGetter.dll」,CallingConvention = CallingConvention.Cdecl)]' –

+0

我以前用簡單的函數使用過P/Invoke,但對於這個DLL,這是它公開的唯一方法。當我添加調用約定時,有趣的是調用失敗,並出現以下錯誤。 「QueryData對棧不平衡,這可能是因爲託管的PInvoke簽名與非託管目標籤名不匹配,請檢查調用約定和PInvoke簽名的參數是否與目標未簽署簽名匹配。 – user1144852

+0

自從我做了任何p/invoke已經很長時間了,但我認爲你的問題是'數據'成員。該函數接受BYTE **(不是BYTE *)。顯然,它在內部分配一個緩衝區,並返回一個指向緩衝區和它的大小的指針。除非你在通話結束後做了一些清理工作,否則可能會導致內存泄漏。 –

回答

2

這裏有兩個問題:首先是將QueryData設置的值分配到DatasizeOfData,這些值指向局部變量。您可以使用refout關鍵字來完成,因此C++中的UINT32* SizeOfData變爲ref System.UInt32 SizeOfData。它們之間的Key differenceout參數在函數調用之前不必被初始化。其次是將C++中定義的非託管數組轉換爲C#。你可以用Marshall.Copy來完成。

有一件事情還不清楚,但應該在文檔中說明 - 每當從C++返回的數組被動態分配並需要在C#中釋放或不在C#中。如果是這樣,你將有內存泄漏,每次調用函數都會增加內存使用量。最簡單的測試方法是調用函數1000000次並檢查內存使用情況。

全碼:

[DllImport("DataGetter.dll"] 
    internal static extern int QueryData(out IntPtr data, out System.UInt32 sizeOfData, bool isDataType); 

    void example() 
    { 
     IntPtr dataPtr; 
     System.UInt32 sizeOfData; 
     bool isDataType = false; 
     int hresult = QueryData(out dataPtr, out sizeOfData, isDataType); 
     var data = new byte[sizeOfData]; 
     Marshal.Copy(dataPtr, data, 0, (int)sizeOfData); 
     // data now contains retreived bytes 
    } 

舊文章: 嘗試用。

[DllImport("DataGetter.dll")] 
    internal static extern int QueryData(ref IntPtr data, ref System.UInt32 sizeOfData, bool isDataType); 

我不知道什麼是PBYTE但我想這是指針字節。 函數應該更改datasizeOfData變量。

+0

這會返回一些內容,但是,你知道如何從IntPtr獲取字節數組嗎? – user1144852

+0

@ user1144852 https://msdn.microsoft.com/en-us/library/ms146631(v=vs.110)。aspx這應該工作 – R2RT

+0

我可以做的代碼片段,如果你給我1小時 – R2RT