gudguy

From the 3rd party C++ header file:

typedef enum
{
VBMTYPE_UNKNOWN = 0,
VBMTYPE_AUDIO = 1,
VBMTYPE_VIDEO = 2
}
VBMTYPE;

typedef enum
{
VBDIR_RECEIVE = 1,
VBDIR_TRANSMIT = 2,
VBDIR_BOTH = 3
}
VBDIR;

typedef enum
{
VBSTRM_MULTICAST = 1,
VBSTRM_TCP = 2,
VBSTRM_TUNNEL = 3,
VBSTRM_UNICAST = 4
}
VBSTREAMTYPE;

typedef void ( CALLBACK *VBASYNCCALLBACK )(
void *pUserParam,
DWORD wErrorCode );

typedef void ( CALLBACK *VBFRAMECALLBACK )(
void *pUserParam,
VBVIDAUXDATA *pVidAuxData
);

BOOL WINAPI VbMediaEnableRender(
HANDLE hDevice,
VBMTYPE nMediaType,
HWND hWnd,
VBFRAMECALLBACK pfnFrameCallback,
void *pUserData
);

BOOL WINAPI VbMediaStartStream(
HANDLE hDevice,
const char *pszIpAddr,
int nConfigId,
VBMTYPE nMediaType,
VBDIR nDirection,
VBSTREAMTYPE nStreamType,
UINT wFlags,
VBASYNCCALLBACK pfnCallback,
void *pUserParam
);
-------------------------------------------
Conversion:

public enum VBMTYPE
{
VBMTYPE_UNKNOWN = 0,
VBMTYPE_AUDIO = 1,
VBMTYPE_VIDEO = 2
}
public enum VBDIR
{
VBDIR_RECEIVE = 1,
VBDIR_TRANSMIT = 2,
VBDIR_BOTH = 3
}
public enum VBSTREAMTYPE
{
VBSTRM_MULTICAST = 1,
VBSTRM_TCP = 2,
VBSTRM_TUNNEL = 3,
VBSTRM_UNICAST = 4
}

public delegate void VBFRAMECALLBACK(
ref IntPtr pUserParam,
VBVIDAUXDATA pVidAuxData
);
public delegate void VBASYNCCALLBACK(
ref IntPtr pUserParam,
uint wErrorCode );

[DllImport("my.dll")]
static extern bool VbMediaEnableRender(IntPtr hDevice, VBMTYPE nMediaType, IntPtr hWnd,
VBFRAMECALLBACK pfnFrameCallback, ref IntPtr pUserData);

[DllImport("my.dll")]
static extern bool VbMediaStartStream(IntPtr hDevice, string pszIpAddr, int nConfigId,
VBMTYPE nMediaType, VBDIR nDirection, VBSTREAMTYPE nStreamType,
uint mFlags, VBASYNCCALLBACK pfnCallback, ref IntPtr pUserParam);


I tried it but a call to VbMediaEnableRender and VbMediaStartStream returns an error code that maps to this description:
"The requested operation is not currently supported by the API."

but this same code works fine in C++. Anyone can tell me whats wrong here

regards,
gudguy



Re: Visual C# General PInvoke conversion works fine but with Win32 error

TaylorMichaelL

How are you getting the Win32 error code By default the marshaler assumes that the Win32 error code isn't used so it might or might not return the correct value. Add SetLastError=true to your DllImport attribute to tell the marshaller to retrieve the error code. Then use Marshal.GetGetLastWin32Error to retrieve the message.

Note that it appears to be your code that you're calling so it might be easier to set up mixed mode debugging and step into your unmanaged code in the debugger to confirm that the data is coming across OK.

Your P/Invoke signature looks OK but you didn't post the callback signature so I can't confirm that.

Michael Taylor - 10/4/07

http://p3net.mvps.org





Re: Visual C# General PInvoke conversion works fine but with Win32 error

gudguy

here's additonal info for callback signatures:

Code Block

typedef struct tagVBOBJLOC
{
int nLeft;
int nRight;
int nUp;
int nDown;
}
VBOBJLOC;

typedef struct tagVBAFILTER
{
int nLevel; /* Current frame level (0-100) */
int nConfig; /* ACF flag = nConfig & 0x80, Threshold Level (0-100) = nConfig & 0x7F */
}
VBAFILTER;

typedef struct tagVBVIDAUXDATA
{
UINT wMdFlags;
int nMdNumObjects;
VBOBJLOC aMdObjects[VBMD_MAX_OBJECTS];
int nNumFilters;
VBAFILTER aFilters[VBMD_MAX_FILTERS];
}
VBVIDAUXDATA;



conversion:

Code Block

[StructLayout(LayoutKind.Sequential)]
public struct VBOBJLOC
{
public int nLeft;
public int nRight;
public int nUp;
public int nDown;
}

[StructLayout(LayoutKind.Sequential)]
public struct VBAFILTER
{
public int nLevel;
public int nConfig;
}

[StructLayout(LayoutKind.Sequential)]
public struct VBVIDAUXDATA
{
public UInt32 wMdFlags;
public int nMdNumObjects;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = VBMD_MAX_OBJECTS)]
VBOBJLOC[] aMdObjects;
public int nNumFilters;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = VBMD_MAX_FILTERS)]
public VBAFILTER[] aFilters;
}


here's how I call it:

Code Block

bool bResult = Global.VbMediaEnableRender(
m_hDevice, // a confirmed valid IntPtr value
Global.VBMTYPE.VBMTYPE_VIDEO, // an enum value
picHandle, // from picturebox.Handle
null, // i can pass null if i don't want the callback
ref x); // where x is IntPtr.Zero

if (!bResult)
{
int err = Marshal.GetLastWin32Error(); // returns 27 w/c is 1B
//ERROR_VNET_UNSUPPORTED 0x1B The requested operation is not currently supported by the API.
}



In my original code i have SetLastError = true so i was able to get the API error which is one of the error codes. What i don't understand is that it works when in C++, but my P/Invoke won't work Sad

regards





Re: Visual C# General PInvoke conversion works fine but with Win32 error

TaylorMichaelL

None of the structures are used in the initial unmanaged call so they shouldn't matter. The parameters are all simple types so they should be fine. The only one that is a little odd is the last parameter. You are passing a reference to an IntPtr which basically means a pointer to a pointer. Remove the ref modifier and see if it works. If it doesn't then
I think the problem lies in the unmanaged API. It doesn't like one of your parameters or it is in a state where it is not ready for use.

Michael Taylor - 10/5/07

http://p3net.mvps.org





Re: Visual C# General PInvoke conversion works fine but with Win32 error

gudguy

Thank you Michael. I removed the ref and it works fine. Also, the call to the method (VbEnableMediaRender) is premature (one method prior to this must be call successfully. i called that method but i didn't notice it failed somewhere) so internally some variables are not in a ready state like you said.

It's SO NICE to have you here! Big big help!

regards,
gudguy