【发布时间】: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);
我知道里面的这个调用使用函数CoTaskMemAlloc为wchar_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.PtrToStringAutoMethod (IntPtr) 将IntPtr转换为string。 (感谢this answer。) -
这不是必须的,pinvoke marshaller 已经调用了 CoTaskMemFree()。通过编写一个调用该函数十亿次的小单元测试来感觉更好。
标签: c# c++ c marshalling wchar-t