2013-10-24 95 views
0

我有選自C DLL導出以下功能:這是編組輸出字節數組的正確方法嗎?

// C 
BOOL WINAPI GetAttributeValue(
     IN  TAG      * psTag, 
     IN  DWORD      dwEltIdx, 
     IN  DWORD      dwAttrIdx, 
     OUT BYTE      * pbBuffer, 
     IN OUT DWORD     * pdwLen) 

// C# 
[DllImport(Simulator.ASSEMBLY, SetLastError = true, CallingConvention = CallingConvention.StdCall)] 
public extern static int GetAttributeValue(
     IntPtr tag_id, 
     int element_index, 
     int attribute_index, 
     [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=4)] 
     byte[] data_buffer, 
     [In, Out] 
     ref int data_length 
    ); 

這是我想要使用它,基於一些答案在這裏SO:

int result = -1; 
byte[] buffer = new byte[2048]; 
int length = buffer.Length; 

result = Simulator.GetAttributeValue(
     tag.NativeId, 
     element_index, 
     attribute_index, 
     buffer, 
     ref length 
    ); 

int[] output = new int[length]; 

for (int i = 0; i < length; i++) 
{ 
    output[i] = buffer[i]; 
} 

return output; 

另一件事我試過是這樣,也是基於對SO找到答案:現在

[DllImport(Simulator.ASSEMBLY, SetLastError = true, CallingConvention = CallingConvention.StdCall)] 
public extern static int GetAttributeValue(
     IntPtr tag_id, 
     int element_index, 
     int attribute_index, 
     IntPtr data_buffer, // changed this 
     [In, Out] 
     ref int data_length 
    ); 

// snip 

GCHandle pinned_array = GCHandle.Alloc(buffer, GCHandleType.Pinned); 
IntPtr pointer = pinned_array.AddrOfPinnedObject(); 

result = Simulator.GetAttributeValue(
     tag.NativeId, 
     element_index, 
     attribute_index, 
     pointer, 
     ref length 
    ); 

// snip, copying stuff to output 

pinned_array.Free(); 
return output; 

,在這兩種情況下,我length似乎正確地填寫,但buffer總是空着。我不是很熟悉P/Invoke和編組,所以我不確定這是否正確。有一個更好的方法嗎?

+0

如果一切都失敗了,可以考慮在C++/cli中編寫一個包裝器......如果你做了很多像這樣的調用,它甚至會更容易編寫和調試。 – 2013-10-24 21:32:18

+0

@ jdv-JandeVaan:幸運的是,我只有兩個帶有緩衝區的API函數,否則這將是一大痛苦。我很高興沒有人發現任何不正確的代碼到目前爲止。> _> –

回答

1

這兩個版本都很好,很難猜測出了什麼問題。 Quacks就像一個不能正確模擬的「模擬器」。標籤ID的IntPtr是奇數。你應該做一些合理的事情,結果就像拋出一個異常,當你得到一個錯誤代碼。

需要傳遞緩衝區的C函數通常很麻煩,您必須猜測正確的緩衝區大小。挑選2048是一個充滿希望的大猜想,當你猜得太低時,確實會出錯。這種功能的通用協議是你必須調用它兩次。首先,data_length的值爲0,然後返回錯誤代碼並將data_length設置爲所需的緩衝區大小。然後用正確大小的緩衝區再次調用它。這只是一個猜測,它確實適合你的問題。

+0

你好! 「標籤ID」只是一個不透明的結構,它確實是一個IntPtr。爲了清楚起見,我刪除了所有錯誤處理內容,因爲在這兩種情況下我都沒有遇到任何錯誤。我可能不得不嘗試使用C可執行文件測試Simulator.ASSEMBLY,只是爲了確保它能正常工作。可能我只是在浪費我的時間而已! :\ –

+0

這當然是你應該驗證的東西,是的。有意將某些數組元素設置爲非零值並檢查它們是否設置爲0也是一個有用的測試。 –

相關問題