我正在使用托管c ++从.NET直接连接统计语言。我在托管C ++中有点绿色,我需要做一些有点棘手的事情。传递给函数的结构用途有一个通用数据指针void*
,用于传递稍后回调中可用的一些有效负载数据。希望我解释一下,在C / C ++中是一个很好用的模式。但是对于我的使用,我需要使用void *
来传递托管对象,我该怎么办?
我正在尝试:
BinaryWriter^ bs=gcnew......;
stream->data=(void*)(%bs);
但它不起作用。 有什么帮助吗?
更新 这似乎有效,但不确定它是否是最佳方式:
pin_ptr<BinaryWriter^> p = &bs;
stream->data=(void*)p;
答案 0 :(得分:1)
您可能想要使用IntPtr类型。
答案 1 :(得分:1)
我的C ++ / CLI有点生疏(所以可能有更好的方法来执行此操作,可能是pin_ptr只是以下的简写)但在C#中使用GCHandle是标准
// getting a fixed pointer
BinaryWriter^ bs=gcnew......;
GCHandle handle = GCHandle.Alloc(bs, GCHandleType.Pinned);
IntPtr ptr = GCHandle.ToIntPtr(handle);
// in callback
GCHandle handle = GCHandle.FromIntPtr(ptr);
BinaryWriter^ bs = (BinaryWriter^)handle.Target;
handle.Free();
当然IntPtr
可以投放到void*
然后再投放。
答案 2 :(得分:1)
C ++ / CLI编译器阻止您执行此操作,这将在运行时严重错误。 “跟踪句柄”的意思是垃圾收集器可以在它压缩堆时移动对象时找回指针并更新其值。将它转换为void *并将该指针传递给本机代码时,它无法执行此操作。该本机代码将在垃圾收集后继续使用该对象,就好像它仍然在其原始位置一样。这是灾难性的。
是的,使用pin_ptr&lt;&gt;是一种解决方法,它将对象固定,使其无法移动。只要pin_ptr&lt;&gt;中的示波器块,它将仅保持固定状态。声明执行,所以请确保本机代码以后仍然不能取消引用该指针。使用GCHandle :: Alloc()获得更长久的引脚,传递GCHandleType :: Pinned。 GCHandle :: AddrOfPinnedObject()返回指针值。
请退后一步,您希望将指针传递给只能从托管代码调用的托管对象。换句话说,本机代码实际上可以使用 nothing 。