Managed Wrappers Around Unmanaged Types
Collapse the table of content
Expand the table of content
This documentation is archived and is not being maintained.

Managed Wrappers Around Unmanaged Types

Visual Studio .NET 2003

Instead of using PInvoke, you may want to use native .NET data types and use the unmanaged data types and functions as part of your managed type implementation. When doing this, you are responsible for translating between managed and unmanaged code.

The following code is an example class definition:

__gc public class City : public IDisposable
{
public:
   City(String* name,short x,short y);
   ~City();
   void Draw(Graphics* g);
   void SetLocation(short x,short y);
   static void DrawCities(Graphics* g,City* cities []);
   void Dispose();
private:
   bool bDisposed;
   CITY * city;
};

The code demonstrates the following concepts:

  • The class implements the IDisposable interface so that it can deterministically clean up the unmanaged resource that it is holding.
  • The class contains an embedded pointer to the unmanaged structure CITY.
  • None of the public methods show that the class is implemented by delegating to unmanaged methods and by manipulating unmanaged data types.

The implementation of the class methods illustrates how the class leverages the unmanaged functions to implement the class behaviors.

City::City(String* name,short x,short y)
{
   bDisposed = false;
   city = new CITY;
   IntPtr p = Marshal::StringToHGlobalAnsi(name);
   city->name = static_cast<char*>(p.ToPointer());
   city->location.x = x;
   city->location.y = y;
}
City::~City()
{
   Dispose();
}
void City::Draw(Graphics* g)
{
   IntPtr hdc = g->GetHdc();
   void* pdc = hdc.ToPointer();
   HDC hDC = static_cast<HDC>(pdc);
   // Calls the unmanaged DrawCity function
   ::DrawCity(hDC,city);
   g->ReleaseHdc(hdc);
}
void City::DrawCities(Graphics* g,City* cities [])
{
   int n = cities->Length;
   for(int i = 0;i < n;i++)
   {
      cities[i]->Draw(g);
   }
}
void City::SetLocation(short x,short y)
{
   city->location.x = x;
   city->location.y = y;
}
void City::Dispose()
{
   if (!bDisposed)
   {
      if (city->name != 0)
         Marshal::FreeHGlobal(IntPtr(city->name));
      delete city;
      bDisposed = true;
   }
}

Because the wrapper class is implemented in Managed Extensions for C++, the class implementation can use unmanaged functions and data types.

Go back to the last step

See Also

Managed Extensions for C++ and Data Marshaling Tutorial

Show:
© 2016 Microsoft