P/Invoke problem

  • Thread starter Thread starter Dirk Reske
  • Start date Start date
D

Dirk Reske

Hello,
I've importet following struct

typedef struct {
DWORD cbStruct;
DWORD fdwStatus;
DWORD_PTR dwUser;
LPBYTE pbSrc;
DWORD cbSrcLength;
DWORD cbSrcLengthUsed;
DWORD_PTR dwSrcUser;
LPBYTE pbDst;
DWORD cbDstLength;
DWORD cbDstLengthUsed;
DWORD_PTR dwDstUser;
DWORD dwReservedDriver[10];
} ACMSTREAMHEADER;

my C# version is

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct ACMSTREAMHEADER
{
public int cbStruct;
public int fdwStatus;
public int dwUser;
public IntPtr pbSrc;
public int cbSrcLength;
public int cbSrcLengthUsed;
public int dwSrcUser;
public IntPtr pbDst;
public int cbDstLength;
public int cbDstLengthUsed;
public int dwDstUser;
public IntPtr dwReservedDriver;
}

is that right?
because it doesn't work

[DllImport("msacm32.dll")]
private static extern int acmStreamPrepareHeader(int mp3Stream,ref
ACMSTREAMHEADER mp3StreamHead,int fdwPrepare);

http://msdn.microsoft.com/library/en-us/multimed/htm/_win32_acmstreamprepare
header.asp

after I call this, my stream handle (mp3Stream) is invalid, so soemthing
must be wrong
Perhaps somebody have worked with the audio compression manager and can help
me
 
I'm not an expert, but I believe this could have to do with how you are
marshalling the memory your pointer points to.

I had a situation where I had to populate a struct and send it to VB6 and
found the following code useful. Perhaps you can find inspiration from it
while waiting for someone else to respond who can give you a better answer.

We noticed that fixed-length strings and arrays need to be marshalled using
the MarshalAs attribute (as shown below). You may want to read up on
GCHandle.Alloc and AddrOfPinnedObject - they may provide you with a little
insight into your problem.

Sorry I can't provide a more complete solution.

Eric

// Convert struct to array of bytes to pass to unmanaged code, because it is
expected in that format by our VB6 routine
private byte[] MakeByteArray(object o)
{
int size = Marshal.SizeOf;
byte[] data = new byte[size];
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr buffer = handle.AddrOfPinnedObject();
Marshal.StructureToPtr(o, buffer, false);
handle.Free();
return data;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode, Pack=4)]
public struct OurUDT
{
public int StdStockTakeNo;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=17)] public char[]
StdDecscno;
public char StdStatus;
public int StdLastChangeUser;
public float /* VB6 Date */ StdLastChangeDate;
}
 
Dirk,
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct ACMSTREAMHEADER
{
public int cbStruct;
public int fdwStatus;
public int dwUser;
public IntPtr pbSrc;
public int cbSrcLength;
public int cbSrcLengthUsed;
public int dwSrcUser;
public IntPtr pbDst;
public int cbDstLength;
public int cbDstLengthUsed;
public int dwDstUser;
public IntPtr dwReservedDriver;
}

is that right?

I'd declare it as

public struct ACMSTREAMHEADER
{
public int cbStruct;
public int fdwStatus;
public IntPtr dwUser;
public IntPtr pbSrc;
public int cbSrcLength;
public int cbSrcLengthUsed;
public IntPtr dwSrcUser;
public IntPtr pbDst;
public int cbDstLength;
public int cbDstLengthUsed;
public IntPtr dwDstUser;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public int[] dwReservedDriver;
}

after I call this, my stream handle (mp3Stream) is invalid,

Do you mean that the function returns MMSYSERR_INVALHANDLE? Can you
post your calling code?



Mattias
 
this.mp3StreamHead = new ACMSTREAMHEADER();
this.mp3StreamHead.pbSrc = Marshal.AllocHGlobal(MP3_BLOCK_SIZE);
this.mp3StreamHead.cbSrcLength = MP3_BLOCK_SIZE;
this.mp3StreamHead.pbDst = Marshal.AllocHGlobal(RawBufSize);
this.mp3StreamHead.cbDstLength = RawBufSize;

this.mp3StreamHead.cbStruct = Marshal.SizeOf(mp3StreamHead);
result = acmStreamPrepareHeader(mp3Stream,ref mp3StreamHead,0);

this call returns 0 (all ok)
but the calls after that (acmStreamConvert, acmStreamClose) returns
INVALID_HANDLE
if I don't call acmStreamPrepareHeader all is fine....but I have to call it

Mattias Sjögren said:
Dirk,
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct ACMSTREAMHEADER
{
public int cbStruct;
public int fdwStatus;
public int dwUser;
public IntPtr pbSrc;
public int cbSrcLength;
public int cbSrcLengthUsed;
public int dwSrcUser;
public IntPtr pbDst;
public int cbDstLength;
public int cbDstLengthUsed;
public int dwDstUser;
public IntPtr dwReservedDriver;
}

is that right?

I'd declare it as

public struct ACMSTREAMHEADER
{
public int cbStruct;
public int fdwStatus;
public IntPtr dwUser;
public IntPtr pbSrc;
public int cbSrcLength;
public int cbSrcLengthUsed;
public IntPtr dwSrcUser;
public IntPtr pbDst;
public int cbDstLength;
public int cbDstLengthUsed;
public IntPtr dwDstUser;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public int[] dwReservedDriver;
}

after I call this, my stream handle (mp3Stream) is invalid,

Do you mean that the function returns MMSYSERR_INVALHANDLE? Can you
post your calling code?



Mattias
 
Dirk,
this call returns 0 (all ok)
but the calls after that (acmStreamConvert, acmStreamClose) returns
INVALID_HANDLE
if I don't call acmStreamPrepareHeader all is fine....but I have to call it

That sounds strange indeed. Unfortunately I don't know enough about
these APIs to guess why. Do you have this working in some other
language? I.e. are you sure that the problem is related to managed
code and P/Invoke, and does not appear when using the same call
sequence in some other language?



Mattias
 
Back
Top