2010-01-04 89 views
2

我有一個通過委託調用的回調函數。在它裏面,我需要處理從記錄過程到達的緩衝區數據。通常在非託管環境中,我可以在dwParam1上執行reinterpret_cast以獲取對象引用。 但在一個管理的上下文中,我怎樣才能將一個DWORD_PTR轉換爲一個託管對象ref?將本機指針轉換爲C++ CLI託管對象引用?

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

回答

2

這裏亞去,或多或少什麼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); 
    } 
} 
+0

我決定做純C++的音頻類,但信息可以得心應手。 感謝您的幫助! – 2010-01-06 04:33:20

1

我不是C++/CLI專家,但一目瞭然我不認爲這是可能的。如果可能的話,這將是非常不安全的。這裏的基本問題是託管引用和本地指針是not the same thing,並且不支持相同的操作集。

是什麼讓我覺得這是不可能的是託管對象可以在內存中移動。垃圾收集操作例如compact和move memory相應地改變了對象的地址。因此,無法獲得被管理對象的原始指針/地址值,因爲任何給定的GC都可能使其失效。

這不完全正確,因爲您可以將對象固定在內存中。但即使如此,我認爲沒有辦法讓C++將任意地址視爲託管句柄。

我認爲一個更安全的方法將是以下。

  1. 纏繞機對象
  2. 內部的管理對象傳遞的原生對象的整個API的
  3. 使用地址的reinterpret_cast要回本機類型,然後安全地訪問您管理的手柄。
+0

你當然可以得到一個原始指針的管理對象,但它是不安全的。您在這裏討論的三步法已經由gcroot/auto_gcroot <>模板實現。實際上,你只是通過IntPtr值傳遞GCHandle。 – 2010-01-04 06:51:52