Marshal wchar_t **从C ++到C#作为out参数?

时间:2016-10-10 10:56:36

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

我在C中的dll中有这个功能,我无法改变它:

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

我知道这个调用内部使用函数wchar_t*CoTaskMemAlloc分配内存。

在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*并且还可以免费使用它?非常感谢任何帮助!

1 个答案:

答案 0 :(得分:0)

感谢@Dai和@IanAbbot的评论,我找到了一个完美的解决方案:

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