Question

I am going mad trying to call a DLL function for days from a C# application.

Here is the definition of the DLL call:

phStatus_t phbalReg_Rd70xUsbWin_Init
                            ( phbalReg_Rd70xUsbWin_DataParams_t * pDataParams,
                              uint16_t  wSizeOfDataParams ) 

Here is the definition of phbalReg_Rd70xUsbWin_DataParams_t:

enter image description here

And here is my C# code for calling the 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));
}

The problem is that I receive a PInvokeStackImbalance exception.

I tried to change type of paramaters with different things and never achieved to get this work. I am sure I am doing something wrong with types, but can't find what. Can someone help me?

Was it helpful?

Solution

The most common explanation is a calling convention mis-match. As written, the unmanaged function declaration uses cdecl. You did not specify a calling convention in your p/invoke and so the default of stdcall is used.

To fix this, specify cdecl in your p/invoke:

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

You also specified only part of the p/invoke declaration. You missed the second parameter. The full declaration should be:

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

The other unknown here is phStatus_t. You've translated that as uint, an unsigned 32 bit integer. We can only take your word that the translation is correct.

Update: From your comment to the question, phStatus_t should be translated as ushort. So, finally, we have:

[DllImport("NxpRdlib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern ushort phbalReg_Rd70xUsbWin_Init(
    ref data_params data_parameters,
    ushort wSizeOfDataParams
);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top