Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# PInvoke封送常量char*失败,为UnmanagedType.LPStr_C#_Pinvoke - Fatal编程技术网

C# PInvoke封送常量char*失败,为UnmanagedType.LPStr

C# PInvoke封送常量char*失败,为UnmanagedType.LPStr,c#,pinvoke,C#,Pinvoke,我无法理解为什么.NET核心编组无法使用一种marshakking方法而不是另一种方法。在下面的示例中,Marshal.PtrToStringAnsi可以成功地从本机dll封送字符串,但是使用[return:MarshalAs(UnmanagedType.LPStr)]属性的相同调用无法成功?还是来自IntPtr的封送只是运气好,还可能访问无效内存,具体取决于操作系统内存管理 C库代码是(编译为C而不是C++): static const char str[]=“你好世界”; __declspe

我无法理解为什么.NET核心编组无法使用一种marshakking方法而不是另一种方法。在下面的示例中,
Marshal.PtrToStringAnsi
可以成功地从本机dll封送字符串,但是使用
[return:MarshalAs(UnmanagedType.LPStr)]
属性的相同调用无法成功?还是来自IntPtr的封送只是运气好,还可能访问无效内存,具体取决于操作系统内存管理

C库代码是(编译为C而不是C++):

static const char str[]=“你好世界”;
__declspec(dllexport)const char*getstr(){
返回str;
}
C#测试程序:

使用系统;
使用System.Runtime.InteropServices;
名称空间CLibraryPinvoke
{
班级计划
{
public const string LIB_NAME=“CLibrary”;
[DllImport(LIB_NAME,EntryPoint=“getstr”)]
公共静态外部程序IntPtr getstrgood();
[DllImport(LIB_NAME,EntryPoint=“getstr”)]
[返回:Marshallas(UnmanagedType.LPStr)]
公共静态外部字符串getstrbad();
静态void Main(字符串[]参数)
{
WriteLine($“getstr={Marshal.PtrToStringAnsi(getstrgood())}”);
//撞车。
WriteLine($“getstr={getstrbad()}”);
}
}
}
执行结果:

getstr=Hello World.
CLibraryPinvoke\bin\Debug\netcoreapp3.1\CLibraryPinvoke.exe (process 31848) exited with code -1073740940.    

PtrToStringAnsi
从返回值指向的缓冲区复制字符串

UnmanagedType.LPStr
从返回值指向的缓冲区复制字符串,然后释放它。使用
CoTaskMemFree
释放
static const char[]
会使程序崩溃

这是因为返回值的语义是,保存结果的内存是在被调用方分配的

同样,如果内存是在被叫端分配的,但不应使用
CoTaskMemFree
释放,则必须将其封送为
IntPtr
,并使用适当的方法自行释放。
对于由
静态常量char[]
备份的内存,适当的方法是不使用它

这要求函数的用户了解函数的实现细节,这不是一件好事。当然,您可以将该函数记录为永远不会释放的返回内存,但它可能不是一个非常有用的函数,如果将来要更改其行为,您将不得不返回一个可能的
静态常量char[]
s.

通过每次分配内存并让.NET运行时管理其余部分,或者让函数接受一个
char*
参数以将响应复制到其中,可以避免所有这一切。

PtrToStringAnsi
从缓冲区复制字符串
UnmanagedType.LPStr
从缓冲区复制字符串并释放它。使用
CoTaskMemFree
释放
static const char[]
会使程序崩溃。@GSerg-您应该回答:-)