1

我正在使用托管 C++ 直接从 .NET 连接统计语言 R。我对托管 C++ 有点陌生,我需要做一些棘手的事情。用于传递给函数的结构有一个通用数据指针void*,用于传递一些可用于稍后回调的有效负载数据。希望我解释过,这是 C/C++ 中一个很好用的模式。但是为了我的使用,我需要使用 that 传递一个托管对象,void *我该怎么办?

我正在尝试:

BinaryWriter^ bs=gcnew......;
stream->data=(void*)(%bs);

但它不起作用。有什么帮助吗?

更新 这似乎有效,但不确定它是否是最好的方法:

pin_ptr<BinaryWriter^> p = &bs;
stream->data=(void*)p;
4

3 回答 3

1

您可能想要使用 IntPtr 类型。

于 2013-09-25T08:45:34.913 回答
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可以投到 avoid*再返回。

于 2013-09-25T11:02:44.633 回答
1

C++/CLI 编译器会阻止您这样做,这将在运行时出现严重错误行为。“跟踪句柄”的要点是垃圾收集器可以在压缩堆时移动对象时找到指针并更新其值。当您将其强制转换为 void* 并将该指针传递给本机代码时,它无法执行此操作。该本机代码将在垃圾回收之后继续使用该对象,就好像它仍在其原始位置一样。那是灾难性的。

是的,使用 pin_ptr<> 是一种解决方法,它固定对象使其无法移动。只要声明 pin_ptr<> 的作用域块执行,它就会保持固定,因此请确保本机代码以后仍不能取消引用该指针。使用 GCHandle::Alloc(),通过 GCHandleType::Pinned,你会得到一个更永久的 pin。GCHandle::AddrOfPinnedObject() 返回指针值。

退后一步,您希望将指针传递给只能从托管代码调用的托管对象。换句话说,本机代码实际上无法处理该 void*。

于 2013-09-25T12:43:45.063 回答