Convert a C struct to C# (an interop problem)

T

~toki

I'm triyng to use this function
int result = NativeMethods.midiOutGetDevCaps( -1, ref pSI,
(uint)Marshal.SizeOf(pSI) );

Docs say that pSI is a struct (below)
[c++]
typedef struct {
WORD wMid;
WORD wPid;
MMVERSION vDriverVersion;
CHAR szPname[MAXPNAMELEN]; // Here's the problem
WORD wTechnology;
WORD wVoices;
WORD wNotes;
WORD wChannelMask;
DWORD dwSupport;
} MIDIOUTCAPS;


This is my code in c#
[C#]
public struct MIDIOUTCAPS {
public int wMid;
public int wPid;
public long vDriverVersion;
public char[] szPname; // Here's the problem
public int wTechnology;
public int wVoices;
public int wNotes;
public int wChannelMask;
public long dwSupport;
}

MIDIOUTCAPS pSI = new MIDIOUTCAPS();
pSI.szPname = new char[32];
int result = NativeMethods.midiOutGetDevCaps( -1, ref pSI,
(uint)Marshal.SizeOf(pSI) );

This code, give me a nullreference error (the callback stop in the
Kernel32.dll)

If i change "public char[] szPname; X public char szPname;" works fine
(don't retrieve the szPname) (I rename too, of course, pSI.szPname = new
char[32];)

"CHAR szPname[MAXPNAMELEN];" is a null-terminated string

Some idea?
 
T

~toki

Hi ~toki, it's simple

[C#]
public struct MIDIOUTCAPS {
public int wMid;
public int wPid;
public long vDriverVersion;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
public char[] szPname;
public int wTechnology;
public int wVoices;
public int wNotes;
public int wChannelMask;
public long dwSupport;
}

Regards,
~toki
:>)

~toki said:
A small question should be "How can i dimension a char 'in line' (in a
structure)"


~toki said:
I'm triyng to use this function
int result = NativeMethods.midiOutGetDevCaps( -1, ref pSI,
(uint)Marshal.SizeOf(pSI) );

Docs say that pSI is a struct (below)
[c++]
typedef struct {
WORD wMid;
WORD wPid;
MMVERSION vDriverVersion;
CHAR szPname[MAXPNAMELEN]; // Here's the problem
WORD wTechnology;
WORD wVoices;
WORD wNotes;
WORD wChannelMask;
DWORD dwSupport;
} MIDIOUTCAPS;


This is my code in c#
[C#]
public struct MIDIOUTCAPS {
public int wMid;
public int wPid;
public long vDriverVersion;
public char[] szPname; // Here's the problem
public int wTechnology;
public int wVoices;
public int wNotes;
public int wChannelMask;
public long dwSupport;
}

MIDIOUTCAPS pSI = new MIDIOUTCAPS();
pSI.szPname = new char[32];
int result = NativeMethods.midiOutGetDevCaps( -1, ref pSI,
(uint)Marshal.SizeOf(pSI) );

This code, give me a nullreference error (the callback stop in the
Kernel32.dll)

If i change "public char[] szPname; X public char szPname;" works fine
(don't retrieve the szPname) (I rename too, of course, pSI.szPname = new
char[32];)

"CHAR szPname[MAXPNAMELEN];" is a null-terminated string

Some idea?
 
G

Guest

Hi, Toki

I met the problem before, but slightly different from yours.
Looks like the definition of character array inside of struct MIDIOUTCAPS is supposed to specify an array size. You just declared a char array. This will not work in C#.
 
C

Chris R

Try this layout.
A WORD is 16 bit (short), not 32(int). A DWORD is 32 bit(ing), not 64
(long).
Make sure to check MMVERSION and use long for 64 bit or int for 32 bit.

[StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
public struct MIDIOUTCAPS {
public short wMid;
public short wPid;
public long vDriverVersion; // is MMVERSION a 64 bit number?
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=32 )]
public string szPname;
public short wTechnology;
public short wVoices;
public short wNotes;
public short wChannelMask;
public int dwSupport;
}

Chris R.

~toki said:
I'm triyng to use this function
int result = NativeMethods.midiOutGetDevCaps( -1, ref pSI,
(uint)Marshal.SizeOf(pSI) );

Docs say that pSI is a struct (below)
[c++]
typedef struct {
WORD wMid;
WORD wPid;
MMVERSION vDriverVersion;
CHAR szPname[MAXPNAMELEN]; // Here's the problem
WORD wTechnology;
WORD wVoices;
WORD wNotes;
WORD wChannelMask;
DWORD dwSupport;
} MIDIOUTCAPS;


This is my code in c#
[C#]
public struct MIDIOUTCAPS {
public int wMid;
public int wPid;
public long vDriverVersion;
public char[] szPname; // Here's the problem
public int wTechnology;
public int wVoices;
public int wNotes;
public int wChannelMask;
public long dwSupport;
}

MIDIOUTCAPS pSI = new MIDIOUTCAPS();
pSI.szPname = new char[32];
int result = NativeMethods.midiOutGetDevCaps( -1, ref pSI,
(uint)Marshal.SizeOf(pSI) );

This code, give me a nullreference error (the callback stop in the
Kernel32.dll)

If i change "public char[] szPname; X public char szPname;" works fine
(don't retrieve the szPname) (I rename too, of course, pSI.szPname = new
char[32];)

"CHAR szPname[MAXPNAMELEN];" is a null-terminated string

Some idea?
 
T

~toki

I found the same solution that you post.
It works now.
But i go to check the long, int & shorts.
Thanks,,


Chris R said:
Try this layout.
A WORD is 16 bit (short), not 32(int). A DWORD is 32 bit(ing), not 64
(long).
Make sure to check MMVERSION and use long for 64 bit or int for 32 bit.

[StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
public struct MIDIOUTCAPS {
public short wMid;
public short wPid;
public long vDriverVersion; // is MMVERSION a 64 bit number?
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=32 )]
public string szPname;
public short wTechnology;
public short wVoices;
public short wNotes;
public short wChannelMask;
public int dwSupport;
}

Chris R.

~toki said:
I'm triyng to use this function
int result = NativeMethods.midiOutGetDevCaps( -1, ref pSI,
(uint)Marshal.SizeOf(pSI) );

Docs say that pSI is a struct (below)
[c++]
typedef struct {
WORD wMid;
WORD wPid;
MMVERSION vDriverVersion;
CHAR szPname[MAXPNAMELEN]; // Here's the problem
WORD wTechnology;
WORD wVoices;
WORD wNotes;
WORD wChannelMask;
DWORD dwSupport;
} MIDIOUTCAPS;


This is my code in c#
[C#]
public struct MIDIOUTCAPS {
public int wMid;
public int wPid;
public long vDriverVersion;
public char[] szPname; // Here's the problem
public int wTechnology;
public int wVoices;
public int wNotes;
public int wChannelMask;
public long dwSupport;
}

MIDIOUTCAPS pSI = new MIDIOUTCAPS();
pSI.szPname = new char[32];
int result = NativeMethods.midiOutGetDevCaps( -1, ref pSI,
(uint)Marshal.SizeOf(pSI) );

This code, give me a nullreference error (the callback stop in the
Kernel32.dll)

If i change "public char[] szPname; X public char szPname;" works fine
(don't retrieve the szPname) (I rename too, of course, pSI.szPname = new
char[32];)

"CHAR szPname[MAXPNAMELEN];" is a null-terminated string

Some idea?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top