gpt4 book ai didi

c# - 从 C++ 接收一个 char* 到 C#,然后再传回

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:45:56 25 4
gpt4 key购买 nike

我在使用第三方 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);

尝试从各种来源阅读,我尝试了以下方法:

    // 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);
}

看来我只是无法获得释放字符串的 API。

现在,这可能只是 API 中的一个错误,但我对此表示怀疑。更有可能是我在做一些根本性的错误。

我所知道的是我的工作集一直在增长。

相关公司提供 Java 包装器,但不会扩展到 .Net 包装器。

非常感谢收到的任何帮助。

布雷特。

最佳答案

我最好的猜测是 IntPtr 不等同于字符串的 char*。因此,当您调用 SW_ReleaseString 时,您并没有提供相同的指针。

您可以做的是拼凑一些 C++CLI 中介。在 C++CLI 中,您可以直接访问 char*,还可以使用 Marshal::PtrToString 和托管字符串指针,以及 String^ .

这是我认为的样子:

C++/命令行界面:

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);
}

然后在 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();

关于c# - 从 C++ 接收一个 char* 到 C#,然后再传回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5304972/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com