Garbage collection

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi,

I am using a MIDI header structure MIDIHDR. The header contains a pointer
lpData to a string sSysEx, which is filled by an API call back routine using
that pointer.
The structure, an instance mhdr of the header, the string and its handle are
declared on main module level:
<StructLayout(LayoutKind.Sequential)> _
Structure MIDIHDR
Dim lpData as Integer
Dim ...(other integer data)
End Structure
Public mhdr As MIDIHDR
Public sSysEx As String = New String("RRR")
Public GCHSysEx as GCHandle = GCHandle.Alloc(sSysEx, GCHandleType.Pinned)

In a particular sub the header is filled and the midi input is started:
mhdr.lpData = GCHSysEx.AddrOfPinnedObject.ToInt32
mhdr. ...etc...
lRet = midiInStart
and the Midi call back routine fills the string. All OK so far.

However, the sub can only be called once. When it is called again, the
Garbage Collector appears to have moved the string and the pointer is
invalid. As far as I understand, that should not happen as the memory is
pinned and the handle is not yet unpinned by a GCHSysEx.Free statement.

Anyone who knows how to pin memory in a correct way or knows about the
'scope' of a pinned object?

Thanks,

Reinier
 
Reinier,
I have not used Pinned memory so I cannot address that issue itself. You may
want to ask "down the hall" in the microsoft.public.dotent.framework.interop
newsgroup as that is where all the interop people hangout.

I would suggest defining lpData as an System.IntPtr instead of an Integer as
it is really a pointer to data & not an Integer. If you ever try to run this
on the 64 bit version of .NET you will have an obscure error that may be
hard to find... IntPtr will be the correct size for a pointer on both 32Bit
..NET and 64Bit .NET!
Structure MIDIHDR Dim lpData as IntPtr
Dim ...(other integer data)
End Structure

mhdr.lpData = GCHSysEx.AddrOfPinnedObject

Hope this helps
Jay
 
Reinier,
Generally IntPtr is the "best" choice for marshaling pointers, unless you
have a specific type (String) that you want to marshal. Integer is a "bad"
idea for the reasons I gave. There is a MarshalAs attribute that you can put
on fields to indicate the type to marshal the values as, unfortunately I
have not used them within structures.

I cannot answer your specific questions, as I suggested before I would
recommend the Interop group.

A very good book on interop that may help (explain the IntPtr thing better)
is Adam Nathan's ".NET and COM - The Complete Interoperability Guide" from
SAMS.

Hope this helps
Jay
 
Jay,

Thanks again for you help.

Reinier


Jay B. Harlow said:
Reinier,
Generally IntPtr is the "best" choice for marshaling pointers, unless you
have a specific type (String) that you want to marshal. Integer is a "bad"
idea for the reasons I gave. There is a MarshalAs attribute that you can put
on fields to indicate the type to marshal the values as, unfortunately I
have not used them within structures.

I cannot answer your specific questions, as I suggested before I would
recommend the Interop group.

A very good book on interop that may help (explain the IntPtr thing better)
is Adam Nathan's ".NET and COM - The Complete Interoperability Guide" from
SAMS.

Hope this helps
Jay
 
Back
Top