c# - 指向 native C++ 堆的指针上的 Marshal.PtrToStructure 是否正常?

标签 c# c++ memory-management interop clr

我有一个使用 PInvoke 在 C# 和 C++ 之间编码数据的应用程序。该应用程序是一个本地 C++ 应用程序,它在内部使用 C# 部分启动 CLR。​​

有时我必须将数据从 C++ 编码到 C#,我正在使用 Marshal.PtrToStructure为了这。 C++ 部分基本上是这样的:

struct X {};

auto xPtr = new X; // somewhere in the application

callCSharp(xPtr); // somewhere else

C# 部分是这样的:

public void callCSharp(IntPtr xPtr)
{
    var x = Marshal.PtrToStructure<X>(xPtr);
}

此代码适用于我的 Windows 10 计算机,但我不确定使用此代码是否会遇到问题。生命周期管理全部在 C++ 中完成,因此我不必在 C# 端分配或释放任何东西。但是我不确定 CLR 是否总是可以访问 native 堆。 xPtr使用 new 分配因此位于 C++ 应用程序的 native 堆上。 Marshal.PtrToStructure<X>(xPtr)然后尝试读取该位置的内存,但我不知道这是否会导致问题。

我读过 this这表明 C++ 应用程序和 CLR 使用相同的堆(即 GetProcessHeap),因此这似乎支持我对 Windows 10 的发现,但对于其他操作系统版本可能有所不同。

我的示例代码是否健全?这里有什么陷阱吗?此代码是否适用于 Windows 7、8 和 10?

最佳答案

是的,只要 C/C++ 代码不释放内存,这是完全合理和安全的。请注意,并不总是需要(或希望)使用 Marshal这里;取决于什么 <X>是的,您也可以以其他方式做到这一点,包括:

  • unsafe (将 void* 转换为 X* )
  • Unsafe.AsRef<X>(...) (将 void* 转换为 ref X )
  • new Span<X>(...) (它从 X 创建了一定数量的 void* 的跨度;跨度就像一个 vector ,但与任意内存对话)

所有这些都是零拷贝方法,这意味着您的 C# 代码然后直接与完全相同的内存空间对话,而不是本地快照;但是如果您取消引用指针(托管或非托管)到一个非引用本地,那么它将制作一个拷贝。

关于c# - 指向 native C++ 堆的指针上的 Marshal.PtrToStructure 是否正常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63561834/

相关文章:

c# - 将 System.Speech.Synthesis 与 Windows10 通用应用程序 (XAML-C#) 结合使用

c# - 无法从 IEnumerable 转换为“System.Collections.Generic.IEqualityComparer

c# - 录制 SWF 并转换为 FLV

c++ - 更快的编辑距离算法

ios - 我想知道 iOS 运行时异常后的内存管理流程

c# - 无法将字符串转换为我创建的枚举类型

C++计算两次之间的时间量

C++ EVP_EncriptUpdate 重写堆栈?

java - 静态变量内存分配

c++ - 分配具有不同数量和大小的项目的特定大小的数组