调用非托管DLL

时间:2014-02-11 15:10:08

标签: c# dll types pinvoke

我很想尝试从C#应用程序调用DLL函数。

以下是DLL调用的定义:

phStatus_t phbalReg_Rd70xUsbWin_Init
                            ( phbalReg_Rd70xUsbWin_DataParams_t * pDataParams,
                              uint16_t  wSizeOfDataParams ) 

以下是phbalReg_Rd70xUsbWin_DataParams_t的定义:

enter image description here

这是我调用DLL的C#代码:

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));
}

问题是我收到PInvokeStackImbalance例外。

我尝试用不同的东西改变参数的类型,但从未实现过这项工作。我确信我做错了类型,但找不到什么。有人能帮助我吗?

1 个答案:

答案 0 :(得分:2)

最常见的解释是调用约定不匹配。如上所述,非托管函数声明使用cdecl。您没有在p / invoke中指定调用约定,因此使用了默认的stdcall。

要解决此问题,请在p / invoke中指定cdecl:

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

您还只指定了p / invoke声明的一部分。你错过了第二个参数。完整的声明应该是:

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

另一个未知的是phStatus_t。您已将其翻译为uint,无符号32位整数。我们只能说出翻译是正确的。

更新:从您的评论到问题,phStatus_t应翻译为ushort。所以,最后,我们有:

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