English 中文(简体)
Cast native pointer to a C++CLI managed object reference?
原标题:

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);
最佳回答

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);
    }
}
问题回答

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.




相关问题
How to read exact number of bytes from a stream (tcp) socket?

In winsock, both the sync recv and the async WSARecv complete as soon as there is data available in a stream socket, regardless of the size specified (which is only the upper limit). This means that ...

AcquireCredentialsHandle returns SEC_E_NO_CREDENTIALS

I created a self-signed certificate (created using OpenSSL) and installed it into the Certificate Store using the Certificates MMC snap-in (CertMgr.msc) on Windows Vista Ultimate. I have managed to ...

Calling Win32 EnumThreadWindows() in C#

I m trying to get a call to EnumThreadWindows working, but I always get a Wrong Parameter-Error, although my code is nearly the same as this example on pinvoke.net. I don t know why this doesn t work: ...

COM Basic links

folks can you provide me the tutorial link or .pdf for learning basic COM?. i do google it.. still i recommend answers of stackoverflow so please pass me.. Thanks

Handling multiple windows WIN32 API

HI I m trying to create an application in the Win32 environment containing more than one window. How do i do that? all the Win32 Tutorials on web i found only showed how to manage one window. How do i ...

Creating a thread in DllMain?

It seems that when a thread is created from within DllMain upon DLL_PROCESS_ATTACH it won t begin until all dll s have been loaded. Since I need to make sure the thread runs before I continue, I get a ...

热门标签