2013-09-24 59 views
4

如果將NULL傳遞給COM接口方法的參數(如果它被定義爲[In, Out] ref int pchEaten)?將NULL傳遞給COM接口方法的參數/輸出參數

例如,考慮如下界面:

[ComImport, Guid ("000214E6-0000-0000-C000-000000000046")] 
[InterfaceType (ComInterfaceType.InterfaceIsIUnknown)] 
internal interface IShellFolder 
{ 
    void ParseDisplayName (
     [In] IntPtr hwnd, 
     [In] IBindCtx pbc, 
     [In, MarshalAs (UnmanagedType.LPWStr)] string pszDisplayName, 
     [In, Out] ref uint pchEaten, 
     [Out] out PIDLIST ppidl, 
     [In, Out] ref SFGAO pdwAttributes); 
    // ... 
} 

MSDN說下列有關pchEaten參數:的指針,該接收被解析的顯示名稱的字符的數目的ULONG值。如果您的應用程序不需要此信息,請將pchEaten設置爲NULL,並且不會返回任何值。pdwAttributes參數也可以設置爲NULL。

但是,當我從C#調用ParseDisplayName方法時,我看不到將null傳遞給ref參數的方法。

如果我從一個DLL調用函數,我可以多次導入一個函數:一個帶有IntPtr參數,一個帶有正確的簽名,並根據需要選擇過載,我需要傳遞和接收值。但是,如果我嘗試在COM中多次導入相同的方法,它將不起作用,因爲方法的順序非常重要,函數指針也會發生變化。

問題:如何使用輸入/輸出參數的值和NULL來調用COM方法?

注意:這只是一個例子。我知道我可以創建一個虛擬變量,將它傳遞給ref參數並忽略返回的值。然而,方法的行爲可能取決於其值是否爲NULL,非空值可能會導致性能成本等,所以我想避免它。

+0

看看這個答案:http://stackoverflow.com/questions/736474/c-how-to-pass-null-to-a-function-期待-a-ref –

+0

@FlorianGl這個問題和答案不包括我的情況,一個COM接口。正如我已經提到的,我知道DLL案例的解決方案。 – Athari

+0

這並不能解決你的問題,但是這個參數必須是'out',而不是'ref'。 – sharptooth

回答

3

它讓我感到你可能試圖太難避免指針。 C#語言支持它們就好,你可以聲明參數爲[In] uint* pchEaten。現在,您擁有以母語提供的所有選項,您可以通過&local以及null。其中local應該是調用方法的局部變量,以便指針穩定並且不必擔心釘住。

但是,您必須聲明方法不安全。當然,這不是當你正確編程:)

4

您可以重新定義界面像這樣的例子:

internal interface IShellFolder 
{ 
    void ParseDisplayName (
     [In] IntPtr hwnd, 
     [In] IBindCtx pbc, 
     [In, MarshalAs (UnmanagedType.LPWStr)] string pszDisplayName, 
     IntPtr pchEaten, 
     [Out] out PIDLIST ppidl, 
     [In, Out] ref SFGAO pdwAttributes); 
    // ... 
} 

如果你想通過空稱呼它:

ParseDisplayName(...., IntPtr.Zero, ...); 

還是喜歡這個,如果你想傳遞一個uint值:

IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint))); 
uint i = 1234; 
Marshal.StructureToPtr(i, p, false); 
ParseDisplayName(...., p, ...); 
i = (uint)Marshal.PtrToStructure(p, typeof(uint)); // read the value back 
Marshal.FreeHGlobal(p); 
+0

+1,會[[Marshal.ReadInt32]](http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.readint32.aspx)用於讀取返回值? – Groo

+0

是否需要分配內存?如果我正確地理解了MSDN([Blittable和Non-Blittable Types](http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx)),blittable類型被固定而不是被複制,並且'int'是blittable。理想情況下,我想複製這種行爲。 – Athari

+0

@格羅 - 好評,我更新了我的帖子。你可以使用Marshal.ReadInt32(並將其轉換爲uint - 未經檢查),但是我已經放置了一個代碼,如果你用任何結構體替換uint,這個代碼就可以工作。 –