Domanda

Come posso inviare un oggetto gestito alla funzione nativa per utilizzarlo?

void managed_function()
{
  Object^ obj = gcnew Object();

  void* ptr = obj ??? // How to convert Managed object to void*?

  unmanaged_function(ptr);
}

// The parameter type should be void* and I can not change the type.
// This function is native but it uses managed object. Because type of ptr could not be 
// Object^ I called it "Unmanaged Function".
void unmanaged_function(void* ptr)
{
  Object^ obj = ptr ??? // How to convert void* to Managed object?

  obj->SomeManagedMethods();
}
È stato utile?

Soluzione 2

Dopo aver cercato su Google, letto MSDN e provato alcuni codici, ho trovato questo metodo per passare un oggetto gestito a una funzione non gestita.

Questi metodi mostrano come convertire Object ^ in void * e convertire void * in Object ^.

using namespace System;
using namespace System::Runtime::InteropServices;

void managed_function() 
{ 
  Object^ obj = gcnew Object();

  // Convert Object^ to void*
  GCHandle handle = GCHandle::Alloc(obj);
  IntPtr pointer = GCHandle::ToIntPtr(handle);
  void* ptr = pointer.ToPointer();

  unmanaged_function(ptr);

  handle.Free();
} 

void unmanaged_function(void* ptr) 
{
  // Convert void* to Object^
  IntPtr pointer(ptr);
  GCHandle handle = GCHandle::FromIntPtr(pointer);
  Object^ obj = (Object^)handle.Target;

  obj->SomeManagedMethods();
} 

Nota: se "unmanaged_function" ha argomenti variabili, questo metodo non funzionerà.

Altri suggerimenti

L'approccio più pulito e migliore è utilizzare gcroot .

Una citazione da MSDN Procedura: dichiarare gli handlein tipi nativi :

Il modello gcroot viene implementato utilizzando le funzionalità della classe di valori System :: Runtime :: InteropServices :: GCHandle, che fornisce "handle" nell'heap della raccolta dei rifiuti.Si noti che gli handle stessi non vengono raccolti in modo indesiderato e vengono liberati quando non sono più utilizzati dal distruttore nella classe gcroot (questo distruttore non può essere chiamato manualmente).Se crei un'istanza di un oggetto gcroot sull'heap nativo, devi chiamare delete su quella risorsa.

Il tuo codice di esempio adattato per utilizzare gcroot (il codice viene compilato ed eseguito utilizzando VS 2010):

using namespace System;
using namespace System::Runtime::InteropServices;

public ref class SomeManagedObject
{
public:
    String^ data;
    SomeManagedObject()
    {
        data = "Initial Data";
    }
    void SomeManagedMethods()
    {
        data = "Changed Data";
    }
};

void unmanaged_function(void* ptr) 
{
    gcroot<SomeManagedObject^>& obj = *((gcroot<SomeManagedObject^>*)ptr);
    obj->SomeManagedMethods();
} 

void managed_function() 
{ 
    // gcroot handles all allocations/deallocation and convertions
    gcroot<SomeManagedObject^>* pObj = new gcroot<SomeManagedObject^>();

    *pObj = gcnew SomeManagedObject();
    unmanaged_function(pObj);

    delete pObj;
} 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top