如何在C ++和C ++之间传递C#对象引用 [英] How to pass C# object references to and from C++

查看:64
本文介绍了如何在C ++和C ++之间传递C#对象引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这是我的用例:

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

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

我可以想到几种方法:

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

是否存在我不知道的类似于选项3的机制?C ++/CLI不是一种选择,因为我想在没有它的情况下支持平台.

解决方案

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

用法

在:

  1. 使用 GCHandleType.Normal GCHandleType.Weak 为您的CLR对象分配 GCHandle .
  2. 通过 GCHandle.ToIntPtr GCHandle 转换为 IntPtr .
  3. 将该 IntPtr 作为您提到的用户数据指针传递到C ++端.

出局:

  1. 从C ++端获取 IntPtr .
  2. 通过 GCHandle.FromIntPtr
  3. IntPtr 转换回 GCHandle
  4. 使用 GCHandle Target 属性获取原始的CLR对象.

当不再从C ++端引用CLR对象时(由于C ++对象被破坏或由于将用户数据指针重置为例如 IntPtr.Zero ),请释放调用 GCHandle.Free .

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

Is there any way to pass C# object references (class types, not structs) into and out of C++ via native interop?

Here's my use case:

I'm trying to write a game engine in C# but want to use a native (C++) physics library. The physics library maintains its own internal state of all the physical bodies and lets the user associate a small amount of data (a pointer) with each body. After a physics simulation tick, the library supplies a list of all physical bodies that moved. I want to iterate over this list and relay all the changes to the corresponding C# objects.

The question is: what's the best way to associate objects in C# with the corresponding physical bodies in C++?

I can think of a couple ways:

  1. Give each physical body an ID of some kind, associate the ID with the physical body in C++, and maintain a map of ID's to corresponding objects in C#. This seems unnecessarily indirect to me, even with an optimized mapping mechanism.
  2. Take advantage of the ability to marshal C# delegates (which can implicitly reference C# object instances) into C++ function pointers. This might be the best way to do it; I don't know how C# implements delegates and what type of overhead this would entail.
  3. Find some other way to refer to C# objects in C++ and associate that reference with each native physical body.

Is there any mechanism like option 3 I don't know of? C++/CLI isn't an option since I want to support platforms without it.

解决方案

I would suggest using the tool that was specifically designed for situations like that, i.e. System.Runtime.InteropServices.GCHandle.

Usage

In:

  1. Allocate a GCHandle for your CLR object with GCHandleType.Normal or GCHandleType.Weak.
  2. Convert the GCHandle to an IntPtr via GCHandle.ToIntPtr.
  3. Pass that IntPtr to the C++ side as the userdata pointer that you mentioned.

Out:

  1. Get IntPtr back from the C++ side.
  2. Convert the IntPtr back to a GCHandle via GCHandle.FromIntPtr
  3. Use the Target Property of the GCHandle to get to the original CLR object.

When the CLR object is no longer being referenced from the C++ side (either because the C++ object was destroyed or because you reset the userdata pointer to e.g. IntPtr.Zero), release the GCHandle by calling GCHandle.Free.

What type of GCHandle you should allocate depends on whether you want the GCHandle to keep the object alive (GCHandleType.Normal) or not (GCHandleType.Weak).

这篇关于如何在C ++和C ++之间传递C#对象引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆