Bre*_*ett 5 c# c++ marshalling char
我有第三方c ++ dll的内存泄漏问题.对于某些调用,dll为字符串分配内存,将其作为char*传递出去,然后期望接收该指针,以便它可以取消分配内存.
以下是头文件中的一些注释,几个返回char*的示例,以及"Release"方法的签名.
(这个dll被称为SW_API,它来自一个贸易交易所 - 如果有人已经包裹了这个,我很乐意和他们交谈!).
/* Strings returned by the API are similarly normal nul-terminated C strings.
* The user should not attempt to change any of the bytes or read past the
* terminating nul of any returned string. All returned strings must be
* released using SW_ReleaseString() once the user is finished with the
* result. Failure to do this will result in memory leaks.
*/
/**
* @typedef const char* SW_XML
* @brief A string containing an XML documents text.
* @note As with all output strings, returned XML must be freed
* by the user. See @ref resource.
* @sa ErrorCodes
*/
typedef const char* SW_XML;
const char* STDAPICALLTYPE SW_GetLastErrorSpecifics();
SW_ErrCode STDAPICALLTYPE SW_DealGetSWML(SW_LoginID lh,
const char* swmlVersion,
SW_DealVersionHandle dealVersionHandle,
SW_XML* resultXML_out);
void STDAPICALLTYPE SW_ReleaseString(const char* buffer);
Run Code Online (Sandbox Code Playgroud)
试图从各种来源阅读,我尝试了以下内容:
// Extern declarations
[DllImport(sw_api_dll, EntryPoint = "_SW_GetLastErrorSpecifics@0", CharSet = CharSet.Ansi)]
public static extern IntPtr SW_GetLastErrorSpecifics();
[DllImport(sw_api_dll, EntryPoint = "_SW_DealGetSWML@16", CharSet = CharSet.Ansi)]
public static extern int SW_DealGetSWML(int lh, string swmlVersion, string dealVersionHandle, [Out] out IntPtr outputSWML);
[DllImport(sw_api_dll, EntryPoint = "_SW_ReleaseString@4", CharSet=CharSet.Ansi)]
public static extern void SW_ReleaseString(IntPtr buffer);
// Using the externs.
private static string GetIntPtrStringAndRelease(IntPtr ptr)
{
string result = Marshal.PtrToStringAnsi(ptr);
API.SW_ReleaseString(ptr);
return result;
}
public static int SW_DealGetSWML(int lh, string swmlVersion, string dealVersionHandle, ref string outputSWML)
{
IntPtr outputSWML_out = new IntPtr();
int result = API.SW_DealGetSWML(lh, swmlVersion, dealVersionHandle, out outputSWML_out);
outputSWML = GetIntPtrStringAndRelease(outputSWML_out);
return result;
}
public static string SW_GetLastErrorSpecifics()
{
IntPtr ptr = API.SW_GetLastErrorSpecifics();
return GetIntPtrStringAndRelease(ptr);
}
Run Code Online (Sandbox Code Playgroud)
看来我只是无法让API释放字符串.
现在,这可能只是API中的一个错误,但我对此表示怀疑.更可能的是我做了一些基本错误的事情.
我所知道的是,我的工作组不断发展.
有问题的公司提供了Java包装器,但不会延伸到.Net包装器.
最感激的任何帮助.
布雷特.
我最好的猜测是 IntPtr 不等于字符串的 char* 。因此,当您调用 SW_ReleaseString 时,您没有提供相同的指针。
你能做的就是整合一些 C++CLI 中介。在 C++CLI 中,您将可以直接访问char*,并能够使用 Marshal::PtrToString 和托管字符串指针,以及String^.
我认为这应该是这样的:
C++/CLI:
String^ GetStringAndRelease(char* ptr)
{
string result = Marshal::PtrToStringAnsi(ptr);
SW_ReleaseString(ptr);
return result;
}
int SW_DealGetSWML(int lh, const char* swmlVersion, const char* dealVersionHandle, String% outputSWML)
{
char* outputSWML_out;
int result = SW_DealGetSWML(lh, swmlVersion, dealVersionHandle, outputSWML_out);
outputSWML = GetStringAndRelease(outputSWML_out);
return result;
}
String^ SW_GetLastErrorSpecifics()
{
char* ptr = SW_GetLastErrorSpecifics();
return GetStringAndRelease(ptr);
}
Run Code Online (Sandbox Code Playgroud)
然后在 C# 中:
[DllImport(your_wrapper_dll, EntryPoint = "_SW_DealGetSWML@16", CharSet = CharSet.Ansi)]
public static extern int SW_DealGetSWML(int lh, string swmlVersion, string dealVersionHandle, [Out] out string outputSWML);
[DllImport(your_wrapper_dll, EntryPoint = "_SW_GetLastErrorSpecifics@0", CharSet = CharSet.Ansi)]
public static extern string SW_GetLastErrorSpecifics();
Run Code Online (Sandbox Code Playgroud)