2010-08-30 17 views
9

我正在嘗試在C#中執行類似this的操作。我發現如何使用P/Invoke from this link從C#調用Win32方法。但是我在實現P/Invoke時遇到了一些困難。如何在使用P/Invoke時將Win32類型映射到C#類型?

例如,我想訪問的方法之一是PdhOpenQuery, 簽名:

PDH_STATUS PdhOpenQuery(
    __in LPCTSTR szDataSource, 
    __in DWORD_PTR dwUserData, 
    __out PDH_HQUERY *phQuery 
); 

我估計相應的C#聲明應該是這樣的

[DllImport("Pdh.dll")] 
    static extern PDH_STATUS PdhOpenQuery(LPCTSTR szDataSource, 
     DWORD_PTR dwUserData, out PDH_HQUERY *phQuery); 

我的問題:

什麼是LPCTSTR,以及它在C#中映射的數據類型?
如何映射指針類型DWORD_PTR? pinvoke文章說DWORD映射到UInt32,但如何指針?
我認爲PDH_STATUS和PDH_HQUERY是庫的特定結構(我還不確定)。我如何繪製這些圖?

什麼是正確的方法聲明,以及如何正確調用它?

回答

17

什麼是LPCTSTR,以及它在C#中映射的數據類型爲 ?

LPCTSTRconst TCHAR*的typedef。

TCHAR是一種企圖抽象出Windows API既存在於「ANSI」(char特定於語言環境的編碼中的字符串)和「Unicode」(UTF-16)版本中的事實。沒有實際的PdhOpenQuery功能;有一個PdhOpenQueryA函數需要採用UTF-16字符串的ANSI字符串和PdhOpenQueryW函數。

C#使用UTF-16字符串,所以您需要更喜歡這些函數的「W」版本。使用PdhOpenQueryW。那麼第一個參數有C++類型const wchar_t*。C#類型是[MarshalAs(UnmanagedType.LPWStr)] string

如何映射指針類型DWORD_PTR? pinvoke文章說DWORD映射到 UInt32,但如何指針?

DWORD_PTR不是指針。這是一個無符號整數整數大到足以讓保存一個指針。等效的C#類型是System.UIntPtr

我覺得PDH_STATUS和PDH_HQUERY是 具體結構圖書館(我 還不確定)。我如何繪製這些圖?

PDH_STATUS似乎只是一個int

PDH_HQUERY是一個指向一個句柄(另一個指針)的指針,但你可以假裝它是一個整數並使用IntPtr

全部放在一起,你的聲明應該是:

[DllImport("Pdh.dll")] 
static extern int PdhOpenQueryW(
    [MarshalAs(UnmanagedType.LPWStr)] string szDataSource, 
    UIntPtr dwUserData, 
    out IntPtr phQuery); 
+0

更正:'UIntPtr'應該是'UIntPtr dwUserData'?另一個問題,應該怎麼稱呼這個方法? – 2010-08-30 07:04:18

+0

反正LPCTSTR可以映射到IntPtr嗎? SHGetFileInfo API(參考:http://msdn.microsoft.com/en-us/library/windows/desktop/bb762179%28v=vs.85%29.aspx)具有「_In_ LPCTSTR pszPath」的第一個參數,並且大多數當時我看到有人用它作爲「字符串」。但在一個例子中,我發現有人認爲它是一個IntPtr ..? (ref:http://stackoverflow.com/a/14293350/1039753) – 2015-01-17 18:52:04

+0

@ArvoBowen:是的,你可以聲明參數爲「IntPtr」,然後在'System.Runtime'中使用'PtrToStringAnsi'或'PtrToStringUni'函數.InteropServices.Marshal'類的字符串。 – dan04 2015-01-20 02:57:16

0
 
[DllImport("Pdh.dll")] 
    static extern Int32 PdhOpenQuery(string szDataSource, 
     IntPtr dwUserData, ref IntPtr phQuery); 
+0

它仍然不能編譯,因爲PDH_STATUS無法識別。你也可以解釋爲什麼String和IntPtr? – 2010-08-30 06:24:22

+0

糟糕,對不起,返回值應該是IntPtr。 IntPtr是非託管指針的.NET包裝。由於句柄通常是指針或與指針大小相同的某個數字,因此IntPtr也用於句柄。爲什麼字符串那麼,因爲LPCTSTR是一個字符串。 – 2010-08-30 06:48:53

+0

嗯,實際上PDH_STATUS只是一個數字,所以最好將它定義爲Int32。 – 2010-08-30 06:53:25

0

IIRC LPCTSTR分解爲: LP ==長指針//從16位到32位的置信轉換

Ç遺物==恆

TSTR == TSTR // TString,類型的佔位符,將取代各種C頭和#defines取代不同類型的字符串

這對你意味着什麼:它是一個指向字符串的指針,對於C#只是使用字符串,你會沒事的。

PDH_STATUS是一個指向DH_STATUS結構體的指針,所以你需要定義一個C#結構來匹配。

有關在標準Windows標頭,結構和函數中使用p/invoke的一些示例,請參閱P/Invoke.Net。該網站是一種klunky,你只需要繼續點擊和擴大左欄中的項目。

P/Invoke沒有很好的文檔記錄,但是一旦映射了結構和外部函數調用,您應該開始工作。

相關問題