6

我想导入这样的函数:

[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 中声明函数有什么问题?

4

1 回答 1

8

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

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

如果其中任何一个不正确(通常是这种情况),那么程序就会出错。

一般来说,最好简单地返回一个IntPtr并手动编组字符串,就像你对PtrToStringUni.

于 2013-04-03T17:14:15.687 回答