Question

Comment puis-je envoyer un objet géré à la fonction native pour l'utiliser?

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();
}
Était-ce utile?

La solution 2

Après avoir googler, lire MSDN et essayer certains codes, j'ai trouvé cette méthode pour transmettre un objet géré à une fonction non gérée.

Ces méthodes montrent comment convertir l'objet ^ en void * et convertir vide * en objet ^.

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

Remarque: Si "Ungingaged_Function" a des arguments de variables, cette méthode ne fonctionnera pas.

Autres conseils

Le nettoyant et la meilleure approche consiste à utiliser gcroot modèle.

Une citation de MSDN Comment: déclarer des poignées dans les types natifs:

Le modèle GCROOT est implémenté à l'aide des installations du système de classe de valeur :: Runtime :: InteropServices :: Gchandle, qui fournit des "poignées" dans le tas de garbage collecté. Notez que les poignées elles-mêmes ne sont pas collectées et sont libérées lorsqu'elles ne sont plus utilisées par le destructeur dans la classe GCROOT (ce destructeur ne peut pas être appelé manuellement). Si vous instanciez un objet GCROOT sur le tas natif, vous devez appeler Supprimer sur cette ressource.

Votre exemple de code adapté à l'utilisation gcroot (Le code compile et s'exécute en utilisant 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;
} 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top