【问题标题】:Marshal wchar_t** from C++ to C# as an out parameter?从 C++ 到 C# 将 wchar_t** 作为输出参数编组?
【发布时间】:2017-02-18 18:46:03
【问题描述】:

我在 C 中的 dll 中有这个函数,但我无法更改它:

extern "C" SIBIO_MULTILANGUAGE_API_C DWORD getLabel(const char* const i_formName, 
                                                    const char* const i_fieldName, 
                                                    wchar_t** i_output);

我知道里面的这个调用使用函数CoTaskMemAllocwchar_t*分配内存。

在 C# 中,我以这种方式包装了这个函数:

[DllImport("sibio_multilanguage_c.dll", EntryPoint = "getLabel", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 _getLabel([In] string i_formName, [In] string i_fieldName, 
                                       [MarshalAs(UnmanagedType.LPWStr)] out string i_output);

static public string getLabel(string i_formName, string i_fieldName)
{
    string str = null;
    UInt32 err = _getLabel(i_formName, i_fieldName, out str);
    if (0 != err)
    {
        throw  new System.IO.FileNotFoundException();
    }
    return str;
}

我能够正确读取wchar_t* 的内容,但以这种方式读取不会释放在 C 函数中分配的内存。

我如何阅读wchar_t* 并同时释放它?非常感谢任何帮助!

【问题讨论】:

  • 我相信您需要调用Marshal.FreeCoTaskMem,但是它需要IntPtr 参数而不是String 实例。您可以将 getLabel 导入更改为使用 IntPtr 并自己进行字符串转换。
  • 你是对的。我想了想,也试过了,但那样我就无法正确阅读内容。可能我做错了什么。现在我也尝试编辑这个问题。
  • 您是否检查过该库是否提供了一个实用函数来清理在其他函数中创建的对象的内存?
  • 如果您遵循@Dai 的建议,您应该可以使用Marshal.PtrToStringAuto Method (IntPtr)IntPtr 转换为string。 (感谢this answer。)
  • 这不是必须的,pinvoke marshaller 已经调用了 CoTaskMemFree()。通过编写一个调用该函数十亿次的小单元测试来感觉更好。

标签: c# c++ c marshalling wchar-t


【解决方案1】:

感谢@Dai 和@IanAbbot cmets,我想出了一个完美的解决方案:

 [DllImport("sibio_multilanguage_c.dll", EntryPoint = "getLabel", CallingConvention = CallingConvention.Cdecl)]
 private static extern UInt32 _getLabel([In] string i_formName, [In] string i_fieldName, 
                                        out IntPtr i_output);

static public string getLabel(string i_formName, string i_fieldName)
{
    IntPtr i_result;
    string str = null;
    UInt32 err = _getLabel(i_formName, i_fieldName, out i_result);
    if (0 != err)
    {
        throw  new System.IO.FileNotFoundException();
    }
    str = Marshal.PtrToStringAuto(i_result);
    Marshal.FreeCoTaskMem(i_result);
    return str;
}

【讨论】:

    猜你喜欢
    • 2011-08-30
    • 2013-06-24
    • 1970-01-01
    • 2021-07-31
    • 2023-03-08
    • 2020-07-06
    • 2012-10-05
    • 2015-04-09
    • 1970-01-01
    相关资源
    最近更新 更多