Как преобразовать void * в тип, который можно использовать в C #? Совместимость между C DLL и C # - PullRequest
3 голосов
/ 16 июля 2010

Я программист на C / C ++, но меня попросили обновить программу, написанную на C #, для связи с устройством.Мои знания C # очень просты.

Предыдущая версия была полностью написана на C #, но теперь API, который фактически обращается к устройству, был изменен на C. Я обнаружил, что я могу импортировать API-функции C с помощьюиспользование:

[DllImport("myapi.dll")]
public static extern int myfunct( 
                                 [MarshalAs(UnmanagedType.LPTStr)] string lpDeviceName,
                                 IntPtr hpDevice);

В C этот прототип функции:

int myFunct( LPTStr lpDeviceName, HANDLE* hpDevice );

Где HANDLE определяется как:

typedef void *HANDLE;

Однако эта функция не работает должным образом,На самом деле, в вызове кода C # какой тип я должен объявить и передать методу C #?

Спасибо за помощь и извините за любой глупый вопрос.

Ответы [ 2 ]

4 голосов
/ 16 июля 2010

На самом деле, это неправильный способ сортировки HANDLE *. Это будет работать, но не будет надежным перед лицом исключений.

Функция, которую вы опубликовали, выглядит как функция создания объекта (она обрабатывает hpDevice как выходной параметр и возвращает int результат состояния).

Правильный способ маршалинга зависит от того, какой именно тип объекта он создает и как он закрывается. Предполагая, что HANDLE закрывается путем вызова CloseHandle (что верно для большинства , но не для всех HANDLE объектов), тогда вы, вероятно, можете использовать один из типов, наследуемых от SafeHandleZeroOrMinusOneIsInvalid. Например, если объект является разделом реестра, используйте SafeRegistryHandle; если это файл, тогда используйте SafeFileHandle.

Если это какой-то тип, для которого нет существующего типа безопасного дескриптора (но для его закрытия используется CloseHandle), вам придется определить свой собственный тип безопасного дескриптора, полученный из SafeHandleZeroOrMinusOneIsInvalid. Если это какой-то тип, который не использует CloseHandle, чтобы закрыть его, вам придется определить свой собственный безопасный тип дескриптора, полученный из SafeHandle.

Как только вы определили правильный SafeHandle -приведенный тип, вы можете использовать его в вызове функции (используя SafeFileHandle в качестве примера):

[DllImport("myapi.dll")]
public static extern int myFunct(
    [MarshalAs(UnmanagedType.LPTStr)] string lpDeviceName,
    out SafeFileHandle hpDevice);
1 голос
/ 16 июля 2010

вы передаете IntPtr вместо ref IntPtr, определение должно выглядеть следующим образом:

[DllImport("myapi.dll")]
public static extern int myfunct( 
    [MarshalAs(UnmanagedType.LPTStr)] string lpDeviceName,
    ref IntPtr hpDevice);
...