Search
Friday, November 21, 2008 ..:: Articles » Design And Architecture » Pinned Object ::.. Register  Login
 Articles By Category
Concurrent Programming
Tutorials
Imaging And Graphics
XML
Declarative Programming
Controls
Lists And Collections
Unit Testing
Design And Architecture
Performance
Client/Server
Fun Stuff

  

 Pinned Object Minimize

Introduction

This article describes a very short helper class to work with unmanaged memory that must be pinned to prevent the garbage collector from moving it. This is a particular requirement when working with the Win32 API's asynchronous I/O methods, which I found myself doing when implementing a USB device interface.

There is no download, simply copy the code from this article--please do not remove the copyright.

The Code

There really isn't much to this code:

  • It uses generics to internally cast the unmanaged memory to the desired managed type.
  • The class maintains an instance of the managed structure.
  • The constructor pins this structure and initializes a pointer suitable for working with Win32 API methods.
  • The ManagedObject property is used to return a managed object that references the unmanaged memory and to copy the managed object to the unmanaged memory. One caveat is that the managed object must be a structure suitable for use with the Marshal class.
  • The Pointer property is used to return the address of the unmanaged memory.
  • The destructor disposes of the unmanaged memory.
  • The class implements IDisposable, so that you can use this class in a "using" block as well.

Here's the code:

// (c) 2007 Marc Clifton
using System;
using System.Runtime.InteropServices;

namespace Clifton.Tools.Interop
{
  /// <summary>
  /// A helper class for pinning a managed structure so that it is suitable for
  /// unmanaged calls. A pinned object will not be collected and will not be moved
  /// by the GC until explicitly freed.
  /// </summary>
  public class PinnedObject<T> : IDisposable where T : struct
  {
    protected T managedObject;
    protected GCHandle handle;
    protected IntPtr ptr;
    protected bool disposed;

    public T ManangedObject
    {
      get 
      {
        return (T)handle.Target;
      }
      set
      {
        Marshal.StructureToPtr(value, ptr, false);
      }
    }

    public IntPtr Pointer
    {
      get { return ptr; }
    }

    public PinnedObject()
    {
      handle = GCHandle.Alloc(managedObject, GCHandleType.Pinned);
      ptr = handle.AddrOfPinnedObject();
    }

    ~PinnedObject()
    {
      Dispose();
    }

    public void Dispose()
    {
      if (!disposed)
      {
        handle.Free();
        ptr = IntPtr.Zero;
        disposed = true;
      }
    }
  }
}

Example

Using Unsafe Pointers In C#

This example illustrates manipulating a PinnedObject using C++ style pointer syntax within an unsafe code block. The code illustrates:

  • Assigning a new structure to the pinned object (testing the ManagedObject setter)
  • Getting the pointer and manipulating the structure via the pointer (testing the Pointer getter)
  • Getting the structure (testing the ManagedObject getter)
using System;

using Clifton.Tools.Interop;

namespace pintest
{
  public struct TestStruct
  {
    public int a;
  }

  public static class Test
  {
    public static void Main()
    {
      PinnedObject<TestStruct> pin = new PinnedObject<TestStruct>();
      TestStruct ts = new TestStruct();
      ts.a = 1;
      pin.ManangedObject = ts;

      unsafe
      {
        TestStruct* p = (TestStruct*)pin.Pointer;
        ++p->a;
      }

    Console.WriteLine(pin.ManangedObject.a);
    }
  }
}

Conclusion

A simple class but hopefully you will find it useful for the strong type management and functionality that it encapsulates.


  

Copyright 2005 Marc Clifton   Terms Of Use  Privacy Statement
Portal engine source code is copyright 2002-2008 by DotNetNuke. All Rights Reserved