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

这是我的用例:

我试图用C#编写游戏引擎,但想使用 native (C++)物理库。物理库维护所有物理物体的内部状态,并允许用户将少量数据(指针)与每个物体关联。进行物理模拟勾号后,该库将提供所有已移动物理物体的列表。我想遍历此列表,并将所有更改中继到相应的C#对象。

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

我可以想到几种方法:

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

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

    最佳答案

    我建议使用专门针对此类情况的工具,即System.Runtime.InteropServices.GCHandle

    用法

    在:

  • GCHandleGCHandleType.Normal为您的CLR对象分配一个GCHandleType.Weak
  • 通过GCHandleIntPtr转换为GCHandle.ToIntPtr
  • 将您的IntPtr作为您提到的userdata指针传递到C++端。

  • 出去:
  • 从C++端获取IntPtr
  • 通过IntPtrGCHandle转换回GCHandle.FromIntPtr
  • 使用TargetGCHandle属性可获取原始CLR对象。

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

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

    10-07 15:04