WAVEOUTCAPS problem

G

Guest

Hi,

I trying to get something that seems to be simple to work: I’m using VS
2005/C#. I want to get the information of my WaveOut devices. The WAVEOUTCAPS
structure is defined in C++ as:

typedef struct {
WORD wMid;
WORD wPid;
MMVERSION vDriverVersion;
TCHAR szPname[MAXPNAMELEN];
DWORD dwFormats;
WORD wChannels;
WORD wReserved1;
DWORD dwSupport;
} WAVEOUTCAPS;

In C# I declare it as:

public struct WAVEOUTCAPS
{
public ushort wMid;
public ushort wPid;
public ulong vDriverVersion;
public char[] szPname;
public ulong dwFormats;
public ushort wChannels;
public ushort wReserved1;
public ulong dwSupport;
}

And later in the code:

WAVEOUTCAPS waveinfo = new WAVEOUTCAPS();
waveinfo.szPname = new char[32];

the waveOutGetDevCaps function is declared as

[DllImport("winmm.dll")]
public static extern int waveOutGetDevCaps(int uDeviceID, ref WAVEOUTCAPS
lpCaps, int uSize);

everything up to here compiles and runs fine. As soon as I call

waveOutGetDevCaps(0, ref waveinfo, Marshal.SizeOf(waveinfo));

my program crashes with the error:

System.Runtime.InteropServices.SafeArrayTypeMismatchException was unhandled
Message="Specified array was not of the expected type."

Any ideas what I’m doing wrong?
 
P

Peter Duniho

[...]
my program crashes with the error:

System.Runtime.InteropServices.SafeArrayTypeMismatchException was
unhandled
Message="Specified array was not of the expected type."

Any ideas what I’m doing wrong?

Maybe you need to explicitly call the Unicode version? The error sure
seems like something that would come up if you tried to pass a C# Unicode
character array to a Win32 ANSI-version function.

I think that the p/invoke stuff should have a way to specify that, but if
not I suppose you could just use "waveOutGetDevCapsW" explicitly.

Pete
 
N

Nicholas Paldino [.NET/C# MVP]

The problem is that the OP has an array declaration but doesn't specify
that it should be an inline array like the original structure. The array
declaration should be:

[StructLayout(LayoutKind.Sequential)]
public struct WAVEOUTCAPS
{
public ushort wMid;
public short wPid;
public ulong vDriverVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAXPNAMELEN)]
public string szPname;
 
P

Peter Duniho

The problem is that the OP has an array declaration but doesn't
specify that it should be an inline array like the original structure.

Ahh. I see that now.

Is it safe to assume that p/invoke will always match up the correct TCHAR
version of a Win32 function? Or are there situations in which that is
actually an issue and needs to be addressed explicitly?
 
N

Nicholas Paldino [.NET/C# MVP]

It is dependent on the value set to the CharSet property of the
StructLayout attribute assigned to the structure.
 
G

Guest

Thanks. Your post with the sample code was very helpful. I would have never
thought about this.

Nicholas Paldino said:
It is dependent on the value set to the CharSet property of the
StructLayout attribute assigned to the structure.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Peter Duniho said:
Ahh. I see that now.

Is it safe to assume that p/invoke will always match up the correct TCHAR
version of a Win32 function? Or are there situations in which that is
actually an issue and needs to be addressed explicitly?
 
P

Peter Duniho

It is dependent on the value set to the CharSet property of the
StructLayout attribute assigned to the structure.

I didn't see that attribute in the original post. That's my point. Can
one rely on the default behavior? Is there a reliable default behavior?
Or is a structure definition without that attribute a bug waiting to be
found?
 
C

Chris Dunaway

Thanks. Your post with the sample code was very helpful. I would have never
thought about this.

In the future, you might find the pinvoke.net website useful. They
also have an add in to make it easy to get pinvoke signatures directly
from VS.

Chris
 
N

Nicholas Paldino [.NET/C# MVP]

Well, I would say that it is a bug. Depending on what version of the
API the OP is going to make the call for, it is up to the OP to set that
flag. Generally, when using structures for A or W versions of APIS which
have embedded strings in them which need to be marshaled (using the
ByValTStr UnmanagedType), it would be erroneous to not include the CharSet
property on the attribute definition.
 
P

Peter Duniho

Well, I would say that it is a bug. Depending on what version of the
API the OP is going to make the call for, it is up to the OP to set that
flag. Generally, when using structures for A or W versions of APIS which
have embedded strings in them which need to be marshaled (using the
ByValTStr UnmanagedType), it would be erroneous to not include the
CharSet
property on the attribute definition.

Okay...thanks! Good to know. :)
 

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