使用P / Invoke时如何将Win32类型映射到C#类型?

我想在C#中做这样的事情。 我发现如何使用此链接中的 P / Invoke 从 C#调用Win32方法。 但是我在实现P / Invoke方面遇到了一些困难。

例如,我想访问的方法之一是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是库的特定结构(我还不确定)。 我该如何映射这些?

什么是正确的方法声明,以及如何正确地调用它?

什么是LPCTSTR,以及它在C#中映射的数据类型是什么?

LPCTSTRconst TCHAR*的typedef。

TCHAR试图抽象出Windows API存在于“ANSI”(特定于语言环境的编码中的字符串)和“Unicode”(UTF-16)版本中的事实。 没有实际的PdhOpenQuery函数; 有一个PdhOpenQueryA函数,它接受一个ANSI字符串和一个采用UTF-16字符串的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); 

iirc LPCTSTR分解为:LP ==长指针//从16位到32位的thunking遗物

C ==常数

TSTR == TStr // TString,一种占位符,可以替换不同类型的字符串,具体取决于各种C头和#defines

它对你意味着什么:它是一个指向字符串的指针,对于C#只是使用字符串,你会没事的。

PDH_STATUS是指向DH_STATUS结构的指针,因此您需要定义要匹配的C#结构。

查看P / Invoke.Net,了解在标准Windows标头,结构和函数上使用p / invoke的一些示例。 该网站有点笨拙,你只需要点击并展开左栏中的项目。

P / Invoke没有很好的文档记录,但是一旦你映射了结构和extern函数调用,你就应该开展业务了。

 [的DllImport( “的Pdh.dll”)]
     static extern Int32 PdhOpenQuery(string szDataSource, 
         IntPtr dwUserData,ref IntPtr phQuery);