[Mono-osx] CoreMidi Design

Miguel de Icaza miguel at novell.com
Mon Feb 14 23:08:08 EST 2011

Hello Peter,

> One of my primary concerns is the following scenario:
> In response to a MIDI device event, a managed callback in the
> MonoMac.CoreMidi code will be called from unmanaged code with a pointer to a
> MidiPacketList struct as a parameter. That callback will raise an event for
> consumption by client code (i.e. code written by developers using MonoMac
> and not wanting to worry about memory allocation issues). I want to include
> the managed-code-wrapped MidiPacketList as a property of the event. But if I
> just wrapped the native object without copying it, it will probably be freed
> after the event has fired, leaving any references the client code might have
> to the MidiPacketList with a pointer to freed memory.
> These are the solutions I'm considering:
> 1. Allocate some unmanaged memory with AllocHGlobal, copy the packet list
> there, and then set the INativeObject.Handle to point to the copy rather
> than the original. Clean up the memory later when Dispose is called.
> 2. Just don't worry about maintaining native objects in this case at all.
> Decode the MidiPacketList to managed objects and move on with life.

I would expose the former, allocate the unmanaged memory for the
MidiPackets and provide high-level accessor methods that provide
access to the underlying representation.   Using IDisposable +
destructors should take care of the memory management problems and
would not impose a penalty on all users of CoreMidi.

You could also support "light" wrapping by not allocating the object
and shifting the responsibility of use to the user, so you would end
up with something like this:

class MidiPacketsList {
   public MidiPacketsList (IntPtr packetStart, bool allocate)
         allocated = allocate;
         if (allocate)
              this.PacketStart = Marshal.AllocHGlobal (ComputeFullSize
              this.PacketStart = packetStart;

    Dispose (bool disposing)
          if (allocated){
              Marshal.FreeHGlobal (PacketStart);
              allocated = false;

More information about the Mono-osx mailing list