从 c++ 返回字符串函数到 VB .Net

发布于 2024-12-14 01:31:54 字数 753 浏览 0 评论 0原文

我试图从 VB.Net 代码调用 C++ 函数,该函数使用 P/Invoke 返回字符串,但它仅返回单个字符。

C 函数声明

  extern "C" __declspec(dllexport) LPSTR Get_GetDescription(HANDLE)

C 函数定义

  LPSTR Get_GetDescription(HANDLE resultBreakDown){
    return LPSTR(((CalcBreakDown*)resultBreakDown)->GetDescription().c_str()); 
}

VB.Net 代码

    <DllImport("FeeEngineDll.dll", CallingConvention:=CallingConvention.Cdecl)> _
    Public Shared Function Get_GetDescription(ByVal resultBreakDown As IntPtr, ByVal indexSubs As Integer, ByVal indexLine As Integer) As <MarshalAsAttribute(LPStr)> String
    End Function

返回类型或编组是否有问题?

I am trying to call C++ function from VB.Net code which returns string using P/Invoke, but it is returning only single character.

C function Declaration

  extern "C" __declspec(dllexport) LPSTR Get_GetDescription(HANDLE)

C function Definition

  LPSTR Get_GetDescription(HANDLE resultBreakDown){
    return LPSTR(((CalcBreakDown*)resultBreakDown)->GetDescription().c_str()); 
}

VB.Net Code

    <DllImport("FeeEngineDll.dll", CallingConvention:=CallingConvention.Cdecl)> _
    Public Shared Function Get_GetDescription(ByVal resultBreakDown As IntPtr, ByVal indexSubs As Integer, ByVal indexLine As Integer) As <MarshalAsAttribute(LPStr)> String
    End Function

Is there any problem with return type or Marshalling?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

淡紫姑娘! 2024-12-21 01:31:54
extern "C" __declspec(dllexport) LPSTR Get_GetDescription(HANDLE)

返回这样的指针是相当危险的,因为不清楚谁拥有该内存,因此谁应该负责释放它。

在 VB 代码中创建缓冲区并将其传递到 DLL 中(其中可以对值进行 memcpy)会更安全。因此我们可以重写 C++ 端,如下所示:

extern "C" __declspec(dllexport) void Get_GetDescription(HANDLE, LPSTR)

void Get_GetDescription(HANDLE resultBreakDown, LPSTR buffer){
    memcpy(buffer,
           ((CalcBreakDown*)resultBreakDown)->GetDescription().c_str(),
           ((CalcBreakDown*)resultBreakDown)->GetDescription().length()+1); 
}

然后重做 VB 代码,如下所示:

<DllImport("FeeEngineDll.dll", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _
Public Shared Sub Get_GetDescription(ByVal resultBreakDown As IntPtr, <MarshalAs(UnmanagedType.LPStr)> ByVal szFilename As StringBuilder)
End Sub

我添加了 < code>CharSet:=CharSet.Ansi 到 DllImport。您的 C++ 代码不使用 unicode 字符,而 VB 可能会使用 unicode 字符,因此最好指定这一点,您可能不需要将其放入,但我喜欢使这些内容明确。

请注意使用 StringBuilder 而不是 String,因为字符串在 VB 中是不可变的。最后,您需要小心地在字符串生成器中为描述分配足够的空间:

Dim buffer As StringBuilder = New StringBuilder(512)

您可以通过在 VB 代码中使用大量数字来实现此目的,就像我刚刚所做的那样。但是,如果您的 C++ 代码复制的字符数量多于您分配的字符数量,这将导致问题。

其他更好的选择是将缓冲区大小传递给 C++ 代码,以便它知道允许写入多少,或者在 C++ 代码中提供一个获取大小函数,可用于确定应该有多少空间分配给缓冲区。

extern "C" __declspec(dllexport) LPSTR Get_GetDescription(HANDLE)

Returning a pointer like this is rather dangerous, as it is not clear who owns the memory and thus who should take responsibility for freeing it.

It would be safer to create the buffer in your VB code and pass it into the DLL where the value can be memcpy'ed in. So we could rewrite the C++ side like:

extern "C" __declspec(dllexport) void Get_GetDescription(HANDLE, LPSTR)

void Get_GetDescription(HANDLE resultBreakDown, LPSTR buffer){
    memcpy(buffer,
           ((CalcBreakDown*)resultBreakDown)->GetDescription().c_str(),
           ((CalcBreakDown*)resultBreakDown)->GetDescription().length()+1); 
}

And then redo the VB code as follows:

<DllImport("FeeEngineDll.dll", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _
Public Shared Sub Get_GetDescription(ByVal resultBreakDown As IntPtr, <MarshalAs(UnmanagedType.LPStr)> ByVal szFilename As StringBuilder)
End Sub

I have added CharSet:=CharSet.Ansi to the DllImport. Your C++ code is not using unicode characters, whereas VB probably will be, so best specify that, you probably don't need to put it in but I like to make these things explicit.

Note the use of StringBuilder instead of String as strings are immutable in VB. Finally, you will need to be careful to allocate enough space in your string builder for the description:

Dim buffer As StringBuilder = New StringBuilder(512)

You can either do this by using a large number in your VB code, as I have just done. This will however, cause problems if your C++ code ever copies more characters than you allocated.

Other better options would either be to pass in the buffer size to the C++ code so that it knows how much it is allowed to write, or to have a get size function in the C++ code that can be used to determine how much space should be allocated for the buffer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文