转换为C ++ CLI托管对象引用的本机指针?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了转换为C ++ CLI托管对象引用的本机指针?相关的知识,希望对你有一定的参考价值。
我有一个通过委托调用的回调。在其中我将需要处理从记录过程到达的缓冲区数据。通常在非托管上下文中,我可以在dwParam1上执行reinterpret_cast来获取对象引用。但是在manged上下文中,如何将DWORD_PTR转换为托管对象ref?
static void WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
ControlLib::SoundDevice^ soudDevice = ?cast_native2managed?(dwParam1);
答案
在这里,或多或少gcroot(根据我上面的评论):
using namespace System;
using namespace System::Runtime::InteropServices;
// track an object by a normal (not pinned) handle, encoded in a DWORD_PTR
DWORD_PTR ParamFromObject(Object^ obj)
{
return reinterpret_cast<DWORD_PTR>(GCHandle::ToIntPtr(GCHandle::Alloc(obj)).ToPointer());
}
static void WaveInProc(PVOID hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
// unwrap the encoded handle...
GCHandle h = GCHandle::FromIntPtr(IntPtr(reinterpret_cast<void*>(dwParam1)));
try
{
// and cast your object back out
SoundDevice^ x = safe_cast<SoundDevice^>(h.Target);
}
finally
{
// remember to free the handle when you're done, otherwise your object will never be collected
GCHandle::Free(h);
}
}
另一答案
我不是C ++ / CLI专家,但我一眼就认为这不可行。如果有可能,那将是非常不安全的。这里的基本问题是托管引用和本机指针是not the same thing,并且不支持同一组操作。
是什么让我觉得这是不可能的,托管对象可以在内存中移动。例如,垃圾收集操作紧凑并移动内存,相应地改变对象的地址。因此,不可能拥有托管对象的原始指针/地址值,因为任何给定的GC都可能使其无效。
这并不严格,因为您可以将对象固定在内存中。但即便如此,我也不认为有办法让C ++将任意地址视为托管句柄。
我认为更安全的方法如下。
- 将托管对象包装在本机对象内
- 在整个API中传递本机对象的地址
- 使用reinterpret_cast返回本机类型,然后安全地访问托管句柄。
以上是关于转换为C ++ CLI托管对象引用的本机指针?的主要内容,如果未能解决你的问题,请参考以下文章