DLLImport属性PInvokeStackImbalance错误

时间:2014-07-07 12:29:44

标签: .net pinvoke dllimport

我试图使用dllImport属性从vb(VS2013 Express)调用非托管dll,如下所示:

<DllImport("armdll32.dll", setlasterror:=True, charset:=CharSet.Ansi)>
Public Shared Function ArmConnect(ByVal port As Integer, ByVal baud As Long, ByRef   serialNumber As String) As Integer

End Function

我正在调用这样的函数:

Dim serialNumber As String = ""

Debug.WriteLine(MicroScribeWrapper.ArmConnect(0, 0, serialNumber))

但是我收到以下错误:

托管调试助手'PInvokeStackImbalance'在'C:\ XXXX'中检测到问题 附加信息:调用PInvoke函数'MicroscribeSDKTest!MicroscribeSDKTest.MicroScribeWrapper :: ArmConnect'使堆栈失衡。这很可能是因为托管PInvoke签名与非托管目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

dll帮助文件中的文档描述了该功能,如下所示:

ArmConnect检测并建立与MicroScribe的连接。 ArmDll32 / ArmDll64将连接到它发现的第一个MicroScribe设备。检测顺序如下: 始终扫描所有USB端口; 如果使用port = 0和baud = 0调用,则扫描所有可用的串行(COM)端口并尝试连接115200波特;否则,以所需的波特率扫描所需的串行端口。 如果在USB端口上发现MicroScribe,则忽略端口号和波特率参数。使用USB连接时,有时需要将多个MicroScribe单元连接到主机。在这样的应用程序中,连接的每个唯一单元可以通过其序列号字符串来标识,由可选参数serialNumber传递。使用此配置时,需要为每个MicroScribe单元运行单独的ArmDLL实例。

        int ArmConnect ( int port, long baud, char *serialNumber = 0 );

我很确定问题与我如何调用ArmConnect方法有关,但我尝试过的所有内容都失败了。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:3)

我在这里可以看到一些问题。

  • 在Windows上的C ++中,long为32位。因此,p / invoke中的baud参数应为Integer
  • 字符串参数serialNumber可能是C字符串。这是指向以null结尾的字符串的指针。这将是p / invoke中的ByVal serialNumber As String
  • 最后是调用约定。如上所述,似乎非托管代码使用cdecl调用约定。你的p / invoke使用stdcall。有可能我认为非托管代码的调用约定实际上是stdcall,而你所包含的文档则忽略了这一点。读取库的头文件会清除它。
  • 我认为该函数不太可能通过调用SetLastError来返回错误。

因此,总之,p / invoke应该是

<DllImport("armdll32.dll", CallingConvention=CallingConvention.Cdecl, _
    CharSet:=CharSet.Ansi)>
Public Shared Function ArmConnect( _
    ByVal port As Integer, _
    ByVal baud As Integer, _
    ByVal serialNumber As String _
) As Integer
End Function

<DllImport("armdll32.dll", CallingConvention=CallingConvention.Stdcall, _
    CharSet:=CharSet.Ansi)>
Public Shared Function ArmConnect( _
    ByVal port As Integer, _
    ByVal baud As Integer, _
    ByVal serialNumber As String _
) As Integer
End Function