MarshalAs(UnmanagedType.LPWStr)和Marshal.PtrToStringUni()之间的区别

时间:2013-04-03 17:09:05

标签: c# .net marshalling dllimport extern

我想导入这样的函数:

[return: MarshalAs(UnmanagedType.LPWStr)]
[DllImport("DLL.dll", EntryPoint="FuncUtf16", ExactSpelling=true, PreserveSig=true, CharSet=CharSet.Unicode)]
public static extern string Func();

但这给我一个错误:

“Windows已在Test.exe中触发了断点。这可能是由于堆损坏,这表示Test.exe或其加载的任何DLL中存在错误。”

当我反复按“继续”时,该功能确实给出了预期的输出。但是,当我有机会上述声明时:

[DllImport("DLL.dll", EntryPoint="FuncUtf16", ExactSpelling=true, PreserveSig=true, CharSet=CharSet.Unicode)]
public static extern IntPtr Func();

(将返回类型更改为IntPtr)并按如下方式调用它:

Dim a As IntPtr = Func()
Dim Str As String = Runtime.InteropServices.Marshal.PtrToStringUni(a)

,我没有错误,它完全正常!使用“MarshalAs”方式在dll中声明一个函数有什么问题?

1 个答案:

答案 0 :(得分:7)

为返回char* / wchar_t*的方法编写PInvoke签名需要非常小心,因为CLR特殊情况string返回类型。它做出以下假设

  • 转换为char*
  • 后,必须释放string的内存
  • 内存分配了CoTaskMemAlloc

如果其中任何一个不正确(通常是这种情况),那么程序将遇到错误。

一般情况下,最好只返回IntPtr并手动封送字符串,就像使用PtrToStringUni一样。