Frage

Wie kann ich ein verwaltetes Objekt an eine native Funktion senden, um es zu verwenden?

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

War es hilfreich?

Lösung 2

Nachdem ich gegoogelt, MSDN gelesen und einige Codes ausprobiert hatte, fand ich diese Methode, um ein verwaltetes Objekt an eine nicht verwaltete Funktion zu übergeben.

Diese Methoden zeigen, wie Sie Object ^ in void * und void * in Object ^ konvertieren.

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

Hinweis: Wenn "unmanaged_function" variable Argumente hat, funktioniert diese Methode nicht.

Andere Tipps

Der sauberere und bessere Ansatz ist die Verwendung von gcroot Vorlage.

Ein Zitat von MSDN Gewusst wie: Deklarieren von Handlesin nativen Typen :

Die gcroot-Vorlage wird mithilfe der Funktionen der Wertklasse System :: Runtime :: InteropServices :: GCHandle implementiert, die "Handles" für den durch Müll gesammelten Heap bereitstellt.Beachten Sie, dass die Handles selbst nicht durch Müll gesammelt und freigegeben werden, wenn sie vom Destruktor in der Klasse gcroot nicht mehr verwendet werden (dieser Destruktor kann nicht manuell aufgerufen werden).Wenn Sie ein gcroot-Objekt auf dem nativen Heap instanziieren, müssen Sie delete für diese Ressource aufrufen.

Ihr Beispielcode, der für die Verwendung von gcroot angepasst wurde (der Code wird mit VS 2010 kompiliert und ausgeführt):

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top