Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I send a managed object to native function to use it?

How can I send a managed object to native function to use it?

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();
}
like image 351
Amir Saniyan Avatar asked Sep 10 '11 12:09

Amir Saniyan


2 Answers

The cleaner and the better approach is to use gcroot template.

A quote from MSDN How to: Declare Handles in Native Types:

The gcroot template is implemented using the facilities of the value class System::Runtime::InteropServices::GCHandle, which provides "handles" into the garbage-collected heap. Note that the handles themselves are not garbage collected and are freed when no longer in use by the destructor in the gcroot class (this destructor cannot be called manually). If you instantiate a gcroot object on the native heap, you must call delete on that resource.

Your sample code adapted to use gcroot (the code compiles and runs using 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;
} 
like image 108
Eddy Shterenberg Avatar answered Sep 20 '22 17:09

Eddy Shterenberg


After googling, reading MSDN and try some codes, I found this method to pass a managed object to an unmanaged function.

These methods show how to convert Object^ to void* and convert void* to 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();
} 

Note: if "unmanaged_function" has variable arguments, this method won't work.

like image 29
Amir Saniyan Avatar answered Sep 20 '22 17:09

Amir Saniyan