Pergunta

Como posso enviar um objeto gerenciado para função nativa para usá-lo?

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();
}
Foi útil?

Solução 2

Depois de pesquisar no Google, ler MSDN e tentar alguns códigos, descobri esse método para passar um objeto gerenciado para uma função não gerenciada.

Esses métodos mostram como converter Object ^ em void * e converter void * em 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" tiver argumentos variáveis, este método não funcionará.

Outras dicas

A abordagem mais limpa e melhor é usar modelo gcroot .

Uma citação do MSDN How to: Declare Handlesem tipos nativos :

O modelo gcroot é implementado usando os recursos da classe de valor System :: Runtime :: InteropServices :: GCHandle, que fornece "alças" para o heap coletado pelo lixo.Observe que os identificadores em si não são coletados como lixo e são liberados quando não estão mais em uso pelo destruidor na classe gcroot (esse destruidor não pode ser chamado manualmente).Se você instanciar um objeto gcroot no heap nativo, deve chamar delete nesse recurso.

Seu código de amostra adaptado para usar gcroot (o código é compilado e executado usando o 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;
} 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top