c# – MarshalAs(UnmanagedType.LPWStr)和Marshal.PtrToStringUni()之间的差异

我想导入这样的函数

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

解决方法

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

>转换为字符串后,必须释放char *的内存
>内存分配了CoTaskMemAlloc

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

一般来说,最好只返回一个IntPtr并手动编组字符串,就像你使用PtrToStringUni一样.

相关文章

目录简介使用JS互操作使用ClipLazor库创建项目使用方法简单测...
目录简介快速入门安装 NuGet 包实体类User数据库类DbFactory...
本文实现一个简单的配置类,原理比较简单,适用于一些小型项...
C#中Description特性主要用于枚举和属性,方法比较简单,记录...
[TOC] # 原理简介 本文参考[C#/WPF/WinForm/程序实现软件开机...
目录简介获取 HTML 文档解析 HTML 文档测试补充:使用 CSS 选...