如何在 vb.net 中声明函数以调用 c++ dll
how to declare function in vb.net to call c++ dll
我需要从 VB.NET 项目调用位于 C++ dll 中的函数。
C++ dll文档中的定义是:
HRESULT GetStatus(LPBYTE lpSize, LPBYTE lpStatus, HWND hWnd = 0)
lpSize
数据:lpStatus
的大小
lpStatus
: 指定存放设备状态的区域指针。
存储状态和以下数据。
需要255个字节space来存储数据
我这样声明函数
<DllImport("cplusplusdll.dll", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.StdCall, EntryPoint:="GetStatus")>
Public Function GetStatus(ByVal lpSize As String, ByRef lpStatus As String, ByVal hwnd As Long) As Integer
End Function
我这样称呼它:
Dim status As String
result = GetStatus("255", status, 0)
但是当我调用时,我收到一个关于 pinvoikeStackImbalance 的错误,pinvoke 签名不匹配...似乎定义不正确...
我尝试了很多组合,但都没有成功。任何帮助将不胜感激。
提前致谢。
LPBYTE
通常会被声明为 ByVal lpSize As Byte()
所以:
Public Function GetStatus(ByVal lpSize As Byte(), ByRef lpStatus As Byte(), ByVal hwnd As Long) As Integer
检查C++函数实际上是StdCall,也可能是CDecl。
编辑
查看您提供的少量信息,我非常怀疑 lpSize
是否被声明为 LPBYTE
,因为它表示 lpStatus
中给出的数组的长度。此外,hWnd
应该是 IntPtr
这里,您似乎正在尝试接收 lpStatus
中提供的 space 中的字符串。我们可以使用 Marshal.AllocHGlobal
来做到这一点,但是使用 StringBuilder
更简单的方法是可用的。 不要为此使用String
:
<DllImport("cplusplusdll.dll", CharSet:=CharSet.Ansi, _
CallingConvention:=CallingConvention.StdCall, EntryPoint:="GetStatus")>
Public Function GetStatus(ByVal lpSize As Integer, <Out> ByVal lpStatus As StringBuilder, ByVal hwnd As IntPtr) As Integer
End Function
Dim status As New StringBuilder(255)
result = GetStatus(status.Length, status, 0)
```
We can also get the `HRESULT` marshaled directly to an exception, if you would like:
````vb
<DllImport("cplusplusdll.dll", CharSet:=CharSet.Ansi, _
CallingConvention:=CallingConvention.StdCall, EntryPoint:="GetStatus", _
PreserveSig = False)>
Public Sub GetStatus(ByVal lpSize As Integer, <Out> ByVal lpStatus As StringBuilder, ByVal hwnd As IntPtr)
End Sub
我需要从 VB.NET 项目调用位于 C++ dll 中的函数。
C++ dll文档中的定义是:
HRESULT GetStatus(LPBYTE lpSize, LPBYTE lpStatus, HWND hWnd = 0)
lpSize
数据:lpStatus
的大小
lpStatus
: 指定存放设备状态的区域指针。
存储状态和以下数据。
需要255个字节space来存储数据
我这样声明函数
<DllImport("cplusplusdll.dll", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.StdCall, EntryPoint:="GetStatus")>
Public Function GetStatus(ByVal lpSize As String, ByRef lpStatus As String, ByVal hwnd As Long) As Integer
End Function
我这样称呼它:
Dim status As String
result = GetStatus("255", status, 0)
但是当我调用时,我收到一个关于 pinvoikeStackImbalance 的错误,pinvoke 签名不匹配...似乎定义不正确...
我尝试了很多组合,但都没有成功。任何帮助将不胜感激。
提前致谢。
LPBYTE
通常会被声明为 ByVal lpSize As Byte()
所以:
Public Function GetStatus(ByVal lpSize As Byte(), ByRef lpStatus As Byte(), ByVal hwnd As Long) As Integer
检查C++函数实际上是StdCall,也可能是CDecl。
编辑
查看您提供的少量信息,我非常怀疑 lpSize
是否被声明为 LPBYTE
,因为它表示 lpStatus
中给出的数组的长度。此外,hWnd
应该是 IntPtr
这里,您似乎正在尝试接收 lpStatus
中提供的 space 中的字符串。我们可以使用 Marshal.AllocHGlobal
来做到这一点,但是使用 StringBuilder
更简单的方法是可用的。 不要为此使用String
:
<DllImport("cplusplusdll.dll", CharSet:=CharSet.Ansi, _
CallingConvention:=CallingConvention.StdCall, EntryPoint:="GetStatus")>
Public Function GetStatus(ByVal lpSize As Integer, <Out> ByVal lpStatus As StringBuilder, ByVal hwnd As IntPtr) As Integer
End Function
Dim status As New StringBuilder(255)
result = GetStatus(status.Length, status, 0)
```
We can also get the `HRESULT` marshaled directly to an exception, if you would like:
````vb
<DllImport("cplusplusdll.dll", CharSet:=CharSet.Ansi, _
CallingConvention:=CallingConvention.StdCall, EntryPoint:="GetStatus", _
PreserveSig = False)>
Public Sub GetStatus(ByVal lpSize As Integer, <Out> ByVal lpStatus As StringBuilder, ByVal hwnd As IntPtr)
End Sub