2014-02-11 2 views
1

Я схожу с ума, пытаясь вызвать функцию DLL в течение нескольких дней из приложения C#.Вызов неуправляемой DLL

Вот определение вызова DLL:

phStatus_t phbalReg_Rd70xUsbWin_Init 
          (phbalReg_Rd70xUsbWin_DataParams_t * pDataParams, 
           uint16_t wSizeOfDataParams) 

Вот определение phbalReg_Rd70xUsbWin_DataParams_t:

enter image description here

А вот мой C# код для вызова DLL:

public static data_params parameters; 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct data_params 
{ 
    internal ushort wId; //Layer ID for this BAL component, NEVER MODIFY! 
    internal byte ucTxSeq; //Sequence counter for packets. 
    [MarshalAs(UnmanagedType.LPStr)] 
    String pDeviceName; 
    internal IntPtr pDeviceHandle; //Handle to the USB device. 
    internal IntPtr pPipeOut; //Handle to Usb Out-pipe. 
    internal IntPtr pPipeIn; //Handle to Usb In-pipe. 
    internal ushort wTimeoutWrMs; //TO value for Usb Write pipe transfer. 
    internal ushort wTimeoutRdMs; //TO value for Usb Read pipe transfer. 
} 

[DllImport("NxpRdlib.dll", EntryPoint = "phbalReg_Rd70xUsbWin_Init")] 
public static extern uint phbalReg_Rd70xUsbWin_Init(ref data_params data_parameters, 

public static unsafe uint connectToPegoda() 
{ 
    parameters = new data_params(); 
    parameters.wId = 0x05; 
    parameters.ucTxSeq = 0; 
    parameters.pDeviceHandle = IntPtr.Zero; 
    parameters.pPipeOut = IntPtr.Zero; 
    parameters.pPipeIn = IntPtr.Zero; 
    parameters.wTimeoutWrMs = 0xFFFF; 
    parameters.wTimeoutRdMs = 0xFFFF; 
    return phbalReg_Rd70xUsbWin_Init(ref parameters, (uint)Marshal.SizeOf(parameters)); 
} 

Проблема в том, что я eive a PInvokeStackImbalance исключение.

Я попытался изменить тип параметров с разными вещами и никогда не добивался этой работы. Я уверен, что я делаю что-то неправильно с типами, но не могу найти что. Кто-нибудь может мне помочь?

+2

Чистая спекуляция здесь: uint16_t. Короче? Тем не менее, вы бросаете Marshal.SizeOf() в uint. Разве это не должно быть? –

+0

Укажите соглашение о вызове. Кроме того, ваша заявка phbalReg_Rd70xUsbWin_Init PInvoke не заполнена в сообщении. Что такое phStatus_t? –

+0

typedef uint16_t phStatus_t phcsBfl_Status_t - это знаковое короткое значение, использующее положительный диапазон. Старший байт: идентификатор категории (группы). младший байт: ошибка. – user3297701

ответ

2

Наиболее распространенным объяснением является неправильное совпадение вызова. Как написано, объявление неуправляемой функции использует cdecl. Вы не указали соглашение о вызове в своем p/invoke и поэтому используется значение stdcall по умолчанию.

Чтобы это исправить, указать Cdecl в вашем P/Invoke:

[DllImport("NxpRdlib.dll", CallingConvention = CallingConvention.Cdecl)] 

Вы также указаны только часть п/ссылаться на заявление. Вы пропустили второй параметр. Полная декларация должна быть:

[DllImport("NxpRdlib.dll", CallingConvention = CallingConvention.Cdecl)] 
public static extern uint phbalReg_Rd70xUsbWin_Init(
    ref data_params data_parameters, 
    ushort wSizeOfDataParams 
); 

других неизвестных здесь phStatus_t. Вы перевели это как uint, 32-битное целое число без знака. Мы можем только принять ваше слово, что перевод правильный.

Update: Ваш комментарий к этому вопросу, phStatus_t следует переводить как ushort. Итак, наконец, у нас есть:

[DllImport("NxpRdlib.dll", CallingConvention = CallingConvention.Cdecl)] 
public static extern ushort phbalReg_Rd70xUsbWin_Init(
    ref data_params data_parameters, 
    ushort wSizeOfDataParams 
); 
+0

Хо, спасибо, ты сделал мой день! – user3297701

Смежные вопросы