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

C++ 从c+返回字符串+;函数到VB.Net,c++,vb.net,pinvoke,C++,Vb.net,Pinvoke,我尝试调用VB.NET代码中的C++函数,它使用P/Unjk返回字符串,但它只返回单个字符。 C函数声明 extern "C" __declspec(dllexport) LPSTR Get_GetDescription(HANDLE) LPSTR Get_GetDescription(HANDLE resultBreakDown){ return LPSTR(((CalcBreakDown*)resultBreakDown)->GetDescription().c_st

我尝试调用VB.NET代码中的C++函数,它使用P/Unjk返回字符串,但它只返回单个字符。 C函数声明

  extern "C" __declspec(dllexport) LPSTR Get_GetDescription(HANDLE)
  LPSTR Get_GetDescription(HANDLE resultBreakDown){
    return LPSTR(((CalcBreakDown*)resultBreakDown)->GetDescription().c_str()); 
}
C函数定义

  extern "C" __declspec(dllexport) LPSTR Get_GetDescription(HANDLE)
  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
_
公共共享函数Get_GetDescription(ByVal resultBreakDown作为IntPtr,ByVal indexSubs作为Integer,ByVal indexLine作为Integer)作为字符串
端函数
返回类型或编组是否有问题

extern "C" __declspec(dllexport) LPSTR Get_GetDescription(HANDLE)
像这样返回指针是相当危险的,因为不清楚谁拥有内存,因此谁应该负责释放内存

在VB代码中创建缓冲区并将其传递到DLL中,在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
您可以通过在VB代码中使用大量数字来实现这一点,就像我刚才所做的那样。但是,如果C++代码复制的字符比分配的多,那么会引起问题。

其他更好的选项要么是将缓冲区大小传递给C++代码,这样它就知道它允许写多少,或者在C++代码中有一个get size函数,可以用来确定缓冲区应该分配多少空间。C++代码从根本上被破坏,它返回一个悬空指针。此外,这是Vista和Wi7中的硬崩溃,因为函数返回必须用COTASKMeMalLoad()分配返回的字符串缓冲区……感谢您对问题的详细了解……我还可以编写一个非托管C++中的代码来释放eg. Void FreeUmanagedString(Valu*p){Dele[]];…并从我的VB.Net代码中调用此函数…此方法更好,或者您在回答中提到的方法更好。我仍然非常赞成我概述的方法。正如Hans在他对这个问题的评论中指出的那样,在DLL中分配内存并在其他地方使用它还有其他潜在的缺陷……我使用了您的方法……但是一个问题来了……缓冲区的额外空间中出现了不均匀的字符……当我显示从非托管代码返回的文本时,OOPS对我使用的代码表示歉意posted不会复制字符串的NULL终止字节,现已修复。只需在长度上加1即可复制额外的字节。