P/Invoke problem

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
 
E

Eric Johannsen

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;
}
 
M

Mattias Sjögren

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
 
D

Dirk Reske

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
 
M

Mattias Sjögren

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
 

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