我有一个使用 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/