Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / November 2004

Tip: Looking for answers? Try searching our database.

Pointer problem with structure MIDIHDR

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Reinier VDW - 17 Nov 2004 18:55 GMT
Hi,

My app uses the API structure MIDIHDR to receive MIDI long
(system-exclusive) messages and I have got a declaration problem.

The SDK declaration (in C) on MIDIHDR reads:
 typedef struct {
    LPSTR lpData
    DWORD dwBufferLength
    DWORD dwBytesRecorded
    DWORD dwUser
    DWORD dwFlags
    and so on
 } MIDIHDR;
where lpData is a pointer 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)> _
  Public Structure MIDIHDR
     Public lpData As Integer
     Public dwBufferLength As Integer
     and so on ...
  End Structure
  Public mhdr As MIDIHDR
  Public sSysEx As String = New String("<data is entered here>")
To prevent garbage collection on the string it is pinned:
  Public GCHSysEx as GCHandle = GCHandle.Alloc(sSysEx, GCHandleType.Pinned)

Then the header is filled:
  mhdr.lpData = GCHSysEx.AddrOfPinnedObject.ToInt32
  mhdr.dwBufferLength = lenMsg
  mhdr.dwFlags = 0
  lengthHeader = Len(mhdr)

The declaration of lpData as Integer in the struct works, but is obviously
incorrect and will not run on 64-bits machines.
It should be:
  Dim lpData As IntPtr
and also
  mhdr.lpData = GCHSysEx.AddrOfPinnedObject
However, this yields the runtime error:
 System.ArgumentException: File I/O of a structure with field 'lpData' of
type 'IntPtr' is not valid
That error is given on the above statement:   lengthHeader = Len(mhdr)
because IntPtr is part of a struct and the VB Len function cannot determine
its length.

My question is how the pointer should be 'managed'?

Another question about MIDIHDR. It seems that this header is garbage
collected, because sometimes an AccessViolationException is thrown when its
handle is used. How should such a structure be pinned?

Thank you for your help.
Reinier
Mattias Sj?gren - 17 Nov 2004 19:36 GMT
>where lpData is a pointer to a string sSysEx, which is filled by an API call
>back routine (using that pointer).

I suggest using an unmanaged memory block allocated with one of the
Marshal.Alloc* methods instead of using a pinned string here. Managed
strings are meant to contain Unicode text, nothing else.

>because IntPtr is part of a struct and the VB Len function cannot determine
>its length.

Use Marshal.SizeOf instead of Len.

Mattias

Signature

Mattias Sjögren [MVP]  mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Reinier VDW - 18 Nov 2004 22:21 GMT
Thanks for your help.
I marshaled the struct MIDIHDR and Marshal.SizeOf is fine.

However, how should I marshal the string sSysEx?
Dim mypointer as IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(sSysEx)) is
not OK as sSysEx is not a struct.
Do you have an example on the Marshal.Alloc* stuff?

Thanks again for your help.

Reinier

"Mattias Sjögren" wrote:

> >where lpData is a pointer to a string sSysEx, which is filled by an API call
> >back routine (using that pointer).
[quoted text clipped - 9 lines]
>
> Mattias
Mattias Sj?gren - 19 Nov 2004 23:56 GMT
>Dim mypointer as IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(sSysEx)) is
>not OK as sSysEx is not a struct.
>Do you have an example on the Marshal.Alloc* stuff?

You said that the called function would fill the buffer right? Then
just allocate a memory block with a fixed size, like this

Dim mypointer as IntPtr = Marshal.AllocHGlobal(size)

Mattias

Signature

Mattias Sjögren [MVP]  mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Reinier VDW - 20 Nov 2004 20:07 GMT
OK, thank you for your help!

Reinier

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.