2013-01-16 33 views
6

假定有與純-C接口類似以下本機函數,從天然DLL導出:對於編組數組,可以使用P/Invoke [In,Out]屬性嗎?

// NativeDll.cpp 

extern "C" void __stdcall FillArray(
    int fillValue, 
    int count, 
    int* data) 
{ 
    // Assume parameters are OK... 

    // Fill the array 
    for (int i = 0; i < count; i++) 
    { 
     data[i] = fillValue; 
    } 
} 

以下的P/Invoke正常工作(與VS2010 SP1測試):

[DllImport("NativeDll.dll", CallingConvention=CallingConvention.StdCall)] 
public static extern void FillArray(
    int fillValue, 
    int count, 
    [In, Out] int[] data 
); 

以及該P /調用,與上述相同,但不[In, Out]屬性

[DllImport("NativeDll.dll", CallingConvention=CallingConvention.StdCall)] 
public static extern void FillArray(
    int fillValue, 
    int count, 
    int[] data 
); 

那麼,那些[In, Out]屬性可選用於封送數組? 他們的目的是什麼,如果有的話? 可以在我們的P/Invoke聲明中省略它們嗎?

回答

16

不,他們不是正好可選。它只是偶然工作。然而,這是一個非常普遍的事故。它可以工作,因爲數組實際上不會被封送。 pinvoke編組人員發現C#數組已經與本地數組兼容,因此跳過創建它的副本的步驟。它只是將數組引腳並將指針傳遞給本機代碼。

這當然是非常有效的,你將不可避免地得到結果,因爲本地代碼直接寫入數組元素。所以[In]和[Out]屬性都不重要。

如果數組元素類型不那麼簡單,它會變得更加模糊。要識別一個結構或類類型不是blittable或其佈局在編組後不匹配的元素類型並不那麼容易,因此編譯器編組人員具有來創建該數組的副本。尤其是佈局不兼容性可能很難識別,因爲託管佈局是不可發現的。並且可以根據所使用的抖動而改變。它可能在x86中工作,但不能在x64上工作,例如,在選擇AnyCPU時非常討厭。獲取它將修改後的副本複製回C#數組確實需要[Out]。

不知道要提出什麼建議,除了沒有人因爲在聲明中明確表示而被解僱。也許你應該總是顯式的,因爲數組元素類型並不簡單,所以你永遠不會發生意外。

+1

呃...我已經花了好幾個小時解決了編譯x86/x64 /'任何CPU'的問題...... – JerKimball

相關問題