【问题标题】:how to declare function in vb.net to call c++ dll如何在 vb.net 中声明函数以调用 c++ dll
【发布时间】:2021-04-21 11:41:39
【问题描述】:

我需要从 VB.NET 项目调用位于 C++ dll 中的函数。

C++ dll文档中的定义是:

HRESULT GetStatus(LPBYTE lpSize, LPBYTE lpStatus, HWND hWnd = 0)

lpSize数据:lpStatus的大小
lpStatus:指定一个区域的指针来存储设备状态。
存储状态和以下数据。
存储数据需要 255 字节空间

我这样声明函数

<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 是一个指向 BYTE 的指针,所以这些是 IntPtr() 并对其进行编组 (Marshal.Copy())。你知道尺寸吗?
  • 如果LPBYTE 确实意味着代表LPSTR,就像它可以从您的用法中理解的那样,并且如果第二个参数应该接收一个字符串,然后GetStatus(ByVal lpSize As String, ByVal lpStatus As StringBuilder, ByVal hwnd As IntPtr) As Integer。我严重怀疑第一个参数,看起来像缓冲区的大小,是一个字符串。如果它确实是一个 LPBYTE 开头,那么它可能是你应该传递一个指向 int 而不是它的字符串表示形式的指针。
  • 我已经用函数信息更新了帖子
  • jimi,谢谢你的回复。大小为 255
  • 信息不足。第一个参数应该指向什么,某种整数或字符串缓冲区?该函数是否通过第一个参数返回实际长度,如果是,如何 - 作为缓冲区中的整数或作为缓冲区中的文本表示?如果需要 255 个字节,为什么首先要有第一个参数?

标签: c# c++ vb.net dll dllimport


【解决方案1】:

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 提供的空间中接收一个字符串。我们可以使用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

【讨论】:

  • 我已经像你所说的那样宣布了。但是怎么称呼呢?如何设置变量和调用函数?
  • 定义中没有任何迹象表明您可以传递string,您知道这是可能的吗?它只是一个字节数组
  • 你能告诉我如何用你修改后的定义从 vb.net 调用 GetStatus 函数吗?
  • GetStatus(mybytearray1, mybytearray2, 0) 在某些情况下可以传递字符串,而无需查看我不知道的函数的文档。您可能还需要自定义编组
  • 谢谢。如何为 mybytearray1 设置值?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-30
相关资源
最近更新 更多