Cast native pointer to a C++\CLI managed object reference?

故事扮演 提交于 2019-12-02 04:46:18

问题


I have a callback that is called through a delegate. Inside it I will need to treat the buffer data that arrive from a record procedure. Normally in a unmanaged context I could do a reinterpret_cast on dwParam1 to get the object reference. But in a manged context how can I cast a DWORD_PTR to a managed object ref?

    static void WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) 
    {
        ControlLib::SoundDevice^ soudDevice = ?cast_native2managed?(dwParam1);

回答1:


Here ya go, more or less what gcroot (per my comment above) does:

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);
    }
}



回答2:


I'm not a C++/CLI expert but at a glance I don't think this is possible. If it were possible it would be very much unsafe. The basic problem here is that managed references and native pointers are not the same thing and don't support the same set of operations.

What makes me think this is not possible is that managed objects can move around in memory. Garbage collection operations for instance compact and move memory which correspondingly changes the addresses of objects. Hence it's not possible to have a raw pointer / address value of a managed object because any given GC could invalidate it.

This is not strictly true as you can pin an object in memory. But even then I don't think there is a way to get C++ to treat an arbitrary address as a managed handle.

I think a much safer approach would be the following.

  1. Wrap the managed object inside of a native object
  2. Pass the address of the native object throughout your API's
  3. Use reinterpret_cast to get back to the native type and then safely access your managed handle.


来源:https://stackoverflow.com/questions/1997576/cast-native-pointer-to-a-c-cli-managed-object-reference

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!