DLLImport -> как обрабатывать РУЧКУ в C # - PullRequest
2 голосов
/ 08 мая 2011

в моем коде C # я хочу импортировать C ++ DLL. Я использую dllimport, и он отлично работает с некоторыми функциями. Но в одной функции я получаю РУЧКУ, которая понадобится мне позже для вызова другой функции.

   [DllImport("SiUSBXp.dll")]
   public static extern int SI_Open(UInt32 deviceNum,ref IntPtr devHandle );   // this function gets the HANDLE
   [DllImport("SiUSBXp.dll")]
   public static extern int SI_Write([In]IntPtr devHandle, [In, Out] byte[] inputByte, UInt32 size,ref UInt32 bytesWritten); // this function needs the HANDLE

В моем коде эти функции называются так:

   IntPtr devHandle = new IntPtr();
   UInt32 bytesWritten = new UInt32();
   byte[] byteArr = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
   SI_Open(0, ref devHandle);
   SI_Write(devHandle, byteArr, 10, ref bytesWritten);

Если я делаю так, я получаю «System.AccessViolationException». Я искал здесь и в Интернете, но не нашел конкретного ответа. Как правильно использовать IntPtr, чтобы он работал? С наилучшими пожеланиями

Toby

Ответы [ 4 ]

1 голос
/ 08 мая 2011

Ваша функция SI_Write очень похожа на WriteFile Windows Kernel32.

Итак, я бы сделал это:

[DllImport("SiUSBXp.dll", SetLastError = true)]
static extern int SI_Open(uint dwDevice, ref IntPtr cyHandle);  

[DllImport("SiUSBXp.dll", SetLastError = true)]
static extern int SI_Write(IntPtr cyHandle, byte[] lpBuffer,
   uint dwBytesToWrite, out uint lpdwBytesWritten);

РЕДАКТИРОВАТЬ : я нашел эту документацию РУКОВОДСТВО ПРОГРАММИСТА USBXPRESS® в Интернете, и там говорится, что прототип SI_Write выглядит намного ближе к WriteFile, чем я думал. Документ гласит:

SI_STATUS SI_Write (HANDLE Handle, LPVOID Buffer, DWORD NumBytesToWrite,
DWORD *NumBytesWritten, OVERLAPPED* o = NULL)

Это означает, что прототип .NET должен быть таким:

[DllImport("SiUSBXp.dll")]
static extern int SI_Write(IntPtr Handle, byte[] Buffer,
   uint NumBytesToWrite, out uint NumBytesWritten, IntPtr o);

o не является обязательным, поэтому вы можете передать IntPtr.Zero.

1 голос
/ 08 мая 2011

Вы делаете классическую ошибку программиста на C, вы не проверяете возвращаемое значение функций.Который говорит вам, была ли сбой функции.Вероятным сценарием является то, что SI_Open () вернул код ошибки.Вы игнорируете его и в любом случае используете значение неинициализированного дескриптора.Kaboom не является чем-то необычным.

Следующая возможная ошибка заключается в том, что вы не используете свойство CallingConvention в выражении [DllImport].Скорее всего, это потребуется, Cdecl используется по умолчанию, если только нативная функция не объявлена ​​с __stdcall.Также отличный способ вызвать kaboom.Если у вас все еще есть проблемы, вам придется отлаживать нативный код.

Кстати, вы избавляетесь от неловкого синтаксиса, используя out вместо ref ,В обеих функциях.

   [DllImport("SiUSBXp.dll", CallingConvention = CallingConvention.Cdecl)]
   public static extern int SI_Open(UInt32 deviceNum, out IntPtr devHandle );
1 голос
/ 08 мая 2011

попробуйте это:

   [DllImport("SiUSBXp.dll")]
   public static extern int SI_Open(UInt32 deviceNum, ref IntPtr devHandle);   // this function gets the HANDLE
   [DllImport("SiUSBXp.dll")]
   public static extern int SI_Write(IntPtr devHandle, ref byte[] inputByte, UInt32 size, ref UInt32 bytesWritten); // this function needs the HANDLE

РЕДАКТИРОВАТЬ:

@ Ганс Пассант прав.Это правильный способ передачи байта [] в параметр LPVOID.ref используется для приведения объекта в LPVOID, но не требуется для массива.Что произойдет, когда вы попробуете это?

   [DllImport("SiUSBXp.dll")]
   public static extern int SI_Write(IntPtr devHandle, byte[] inputByte, UInt32 size, ref UInt32 bytesWritten); // this function needs the HANDLE

Пробовали ли вы ответ, который дал @Simon Mourier?Он первым предоставил эту декларацию, и его ответ заслуживает принятия.

0 голосов
/ 12 апреля 2012

плохо: static extern void DoStuff(**byte[] inputByte**);

хорошо: static extern void DoStuff(**[In, MarshalAs(UnmanagedType.LPArray)] byte[] inputByte**);

...