Как передать тип, допускающий значение NULL, в функцию P/invoked

У меня есть несколько функций p/invoked (но в данный момент я переписываю свой код, поэтому я убираюсь), и я хочу знать, как использовать/передавать тип, допускающий значение NULL, в качестве одного из параметров. работа с типами int не является проблемой, но учитывая следующее:

[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, int? enumerator, IntPtr hwndParent, uint Flags);

Я хотел бы иметь возможность передавать параметр Guid как тип, допускающий значение NULL. На данный момент я могу назвать это так:

SetupDiGetClassDevs(ref tGuid, null, IntPtr.Zero, (uint)SetupDiFlags.DIGCF_PRESENT );

но мне нужно, чтобы первый параметр также можно было передать как null.


person Dark Star1    schedule 26.06.2009    source источник
comment
@River Mine - не оскорбительный вопрос, поскольку он был задан еще в 2009 году;)   -  person Dark Star1    schedule 28.12.2017
comment
новый представляет собой попытку создать каноническую версию этой проблемы с большим количеством более общих решений.   -  person River    schedule 28.12.2017


Ответы (1)


Невозможно передать тип Nullable в функцию PInvoke без некоторых... интересных манипуляций с байтами в собственном коде, которые почти наверняка не то, что вам нужно.

Если вам нужна возможность передать значение структуры как NULL в собственный код, объявите перегрузку вашей декларации PInvoke, которая принимает IntPtr вместо структуры и передает IntPtr.Zero

[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, ref int enumerator, IntPtr hwndParent, uint Flags);
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, IntPtr enumerator, IntPtr hwndParent, uint Flags);

Примечание. Я добавил класс ref к первой подписи. Если собственная подпись может принимать значение NULL, скорее всего, это тип указателя. Следовательно, вы должны передавать типы значений по ссылке.

Теперь вы можете совершать звонки, как показано ниже.

if (enumerator.HasValue) { 
  SetupDiGetClassDevs(someGuid, ref enumerator.Value, hwnd, flags);
} else {
  SetupDiGetClassDevs(someGuid, IntPtr.Zero, hwnd, flags);
}
person JaredPar    schedule 26.06.2009
comment
До сих пор я перегружал свои функции P/invoke. Мой вопрос состоял в том, чтобы посмотреть, смогу ли я сократить это и еще немного привести в порядок свой код, не перегружая его. До сих пор мне удавалось без проблем выдать int (параметр 2) за значение, допускающее значение NULL. Означает ли это, что это ограничение применяется только к структурированным типам? Другое дело, что в одном воплощении моего кода я определил параметр 2 как [MarshalAs(UnmanagedType.LPTStr)] string Enumerator, что также позволяет мне обнулить этот параметр во время использования. - person Dark Star1; 26.06.2009
comment
Мои извинения... Я не могу обойтись без обнуляемого int :) - person Dark Star1; 26.06.2009