如何将 C# 对象引用传入和传出 C++

Jo *_*tes 4 c# c++ pinvoke

有没有办法通过本机互操作将 C# 对象引用(类类型,而不是结构)传入和传出 C++?

这是我的用例:

我正在尝试用 C# 编写游戏引擎,但想使用本机 (C++) 物理库。物理库维护它自己的所有物理身体的内部状态,并让用户将少量数据(一个指针)与每个身体相关联。在物理模拟滴答之后,库提供所有移动的物理实体的列表。我想遍历这个列表并将所有更改中继到相应的 C# 对象。

问题是:将 C# 中的对象与 C++ 中的相应物理体相关联的最佳方法是什么?

我可以想到几种方法:

  1. 给每个物理身体一个某种类型的 ID,在 C++ 中将 ID 与物理身体相关联,并在 C# 中维护一个 ID 到相应对象的映射。即使使用优化的映射机制,这对我来说似乎也是不必要的间接。
  2. 利用将 C# 委托(可以隐式引用 C# 对象实例)编组到 C++ 函数指针中的能力。这可能是最好的方法;我不知道 C# 如何实现委托以及这会带来什么类型的开销。
  3. 寻找其他方式在 C++ 中引用 C# 对象,并将该引用与每个原生物理体相关联。

有没有我不知道的选项 3 之类的机制?C++/CLI 不是一个选项,因为我想支持没有它的平台。

Pau*_*oke 5

我建议使用专为这种情况设计的工具,即System.Runtime.InteropServices.GCHandle.

用法

在:

  1. GCHandle使用GCHandleType.Normal或为 CLR 对象分配 a GCHandleType.Weak
  2. 将 转换GCHandleIntPtrvia GCHandle.ToIntPtr
  3. IntPtr将其作为您提到的 userdata 指针传递给 C++ 端。

出去:

  1. 获得IntPtr从C ++侧回来。
  2. IntPtr背面转换为过GCHandleGCHandle.FromIntPtr
  3. 使用 的Target属性GCHandle获取原始 CLR 对象。

当不再从 C++ 端引用 CLR 对象时(因为 C++ 对象被破坏或因为您将 userdata 指针重置为 eg IntPtr.Zero),请GCHandle通过调用GCHandle.Free.

GCHandle您应该分配哪种类型取决于您是否希望GCHandle使对象保持活动状态 ( GCHandleType.Normal) 或不 ( GCHandleType.Weak)。