Я пытаюсь сделать что-то вроде этого в C #. Я узнал, как вызывать методы Win32 из C #, используя P / Invoke по этой ссылке . Однако я столкнулся с некоторыми трудностями при реализации 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 и к какому типу данных это отображается в С#?
LPCTSTR
— это определение типа для const TCHAR*
.
TCHAR
— это попытка абстрагироваться от того факта, что Windows API существует как в «ANSI» (строки char
в кодировке, зависящей от локали), так и в «Unicode» (UTF-16). версии. Фактической функции PdhOpenQuery
нет; есть функция PdhOpenQueryA
, которая принимает строку ANSI, и функция PdhOpenQueryW
, которая принимает строку UTF-16.
В 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-битного преобразования
C == Константа
TSTR == TStr // TString, что-то вроде заполнителя, который будет замещать разные типы строк в зависимости от различных Заголовки C и #define
что это значит для вас: это указатель на строку, для C# просто используйте строку, и все будет в порядке.
PDH_STATUS — это указатель на структуру DH_STATUS, поэтому вам потребуется определить соответствующую структуру C#.
Ознакомьтесь с P/Invoke.Net для некоторых примеров использования p/invoke для стандартных заголовков, структур и функций Windows. Веб-сайт довольно неуклюж, вам просто нужно продолжать нажимать и расширять элементы в левой колонке.
P/Invoke плохо документирован, но как только вы сопоставите структуру и внешний вызов функции, вы должны быть в деле.
[DllImport("Pdh.dll")] static extern Int32 PdhOpenQuery(string szDataSource, IntPtr dwUserData, ref IntPtr phQuery);