从 c++ 返回字符串函数到 VB .Net
我试图从 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
返回这样的指针是相当危险的,因为不清楚谁拥有该内存,因此谁应该负责释放它。
在 VB 代码中创建缓冲区并将其传递到 DLL 中(其中可以对值进行 memcpy)会更安全。因此我们可以重写 C++ 端,如下所示:
然后重做 VB 代码,如下所示:
我添加了 < code>CharSet:=CharSet.Ansi 到 DllImport。您的 C++ 代码不使用 unicode 字符,而 VB 可能会使用 unicode 字符,因此最好指定这一点,您可能不需要将其放入,但我喜欢使这些内容明确。
请注意使用
StringBuilder
而不是String
,因为字符串在 VB 中是不可变的。最后,您需要小心地在字符串生成器中为描述分配足够的空间:您可以通过在 VB 代码中使用大量数字来实现此目的,就像我刚刚所做的那样。但是,如果您的 C++ 代码复制的字符数量多于您分配的字符数量,这将导致问题。
其他更好的选择是将缓冲区大小传递给 C++ 代码,以便它知道允许写入多少,或者在 C++ 代码中提供一个获取大小函数,可用于确定应该有多少空间分配给缓冲区。
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:
And then redo the VB code as follows:
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 ofString
as strings are immutable in VB. Finally, you will need to be careful to allocate enough space in your string builder for the description: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.