views:

268

answers:

1

I'm having a hard time here trying to find a solution for my problem.

I'm trying to convert a client API funktion from C++ to VB.NET, and i think have some problems with the callback function.

parts of the C++ code:

typedef struct{

BYTE    m_bRemoteChannel;
BYTE    m_bSendMode;
BYTE    m_nImgFormat;  // =0 cif ; = 1 qcif
char    *m_sIPAddress;
char    *m_sUserName;
char    *m_sUserPassword;
BOOL    m_bUserCheck;
HWND    m_hShowVideo;

}CLIENT_VIDEOINFO, *PCLIENT_VIDEOINFO;

CPLAYER_API LONG __stdcall MP4_ClientStart(PCLIENT_VIDEOINFO pClientinfo,void(CALLBACK *ReadDataCallBack)(DWORD nPort,UCHAR *pPacketBuffer,DWORD nPacketSize));

void CALLBACK ReadDataCallBack(DWORD nPort,UCHAR *pPacketBuffer,DWORD nPacketSize)

{ TRACE("%d\n",nPacketSize); }

    .....
aa5.m_sUserName = "123";
aa5.m_sUserPassword="w";
aa5.m_bUserCheck = TRUE;

MP4_ClientSetTTL(64);
nn1 = MP4_ClientStart(&aa5,ReadDataCallBack);
if (nn1 == -1)
{
    MessageBox("error");
    return;
}

SDK description:

  1. MP4_ClientStart

This function starts a connection. The format of the call is:

LONG __stdcall MP4_ClientStart(PCLIENT_VIDEOINFO pClientinfo, void(*ReadDataCallBack)(DWORD nChannel,UCHAR *pPacketBuffer,DWORD nPacketSize))

Parameters pClientinfo holds the information. of this connection.

nChannel holds the channel of card.

pPacketBuffer holds the pointer to the receive buffer.

nPacketSize holds the length of the receive buffer.

Return Values If the function succeeds the return value is the context of this connection. If the function fails the return value is -1.

Remarks

typedef struct{

BYTE m_bRemoteChannel;

BYTE m_bSendMode;

BYTE m_bImgFormat;

char *m_sIPAddress;

char *m_sUserName;

char *m_sUserPassword;

BOOL m_bUserCheck;

HWND m_hShowVideo;

} CLIENT_VIDEOINFO, * PCLIENT_VIDEOINFO;

m_bRemoteChannel holds the channel which the client wants to connect to.

m_bSendMode holds the network mode of the connection.

m_bImgFormat : Image format, 0 is main channel video, 1 is sub channel video

m_sIPAddress holds the IP address of the server.

m_sUserName holds the user’s name.

m_sUserPassword holds the user’s password.

m_bUserCheck holds the value whether sends the user’s name and password or not.

m_hShowVideo holds Handle for this video window.

If m_hShowVideo holds NULL, the client can be record only without decoder.

If m_bUserCheck is FALSE, we will send m_sUserName and m_sUserPassword as NULL, else we will send each 50 bytes.

The length of m_sIPAddress and m_sUserName must be more than 50 bytes.

ReadDataCallBack: When the library receives a packet from a server, this callback is called.


My VB.Net code:

Imports System.Runtime.InteropServices

Public Class Form1

Const WM_USER = &H400

Public Structure CLIENT_VIDEOINFO
    Public m_bRemoteChannel As Byte
    Public m_bSendMode As Byte
    Public m_bImgFormat As Byte
    Public m_sIPAddress As String
    Public m_sUserName As String
    Public m_sUserPassword As String
    Public m_bUserCheck As Boolean
    Public m_hShowVideo As Long 'hWnd                      
End Structure


Public Declare Function MP4_ClientSetNetPort Lib "hikclient.dll" (ByVal dServerPort As Integer, ByVal dClientPort As Integer) As Boolean
Public Declare Function MP4_ClientStartup Lib "hikclient.dll" (ByVal nMessage As UInteger, ByVal hWnd As System.IntPtr) As Boolean


<DllImport("hikclient.dll")> Public Shared Function MP4_ClientStart(ByVal Clientinfo As CLIENT_VIDEOINFO, ByRef ReadDataCallBack As CALLBACKdel) As Long
End Function


Public Delegate Sub CALLBACKdel(ByVal nPort As Long, <MarshalAs(UnmanagedType.LPArray)> ByRef pPacketBuffer As Byte(), ByVal nPacketSize As Long)


Public Sub CALLBACK(ByVal nPort As Long, <MarshalAs(UnmanagedType.LPArray)> ByRef pPacketBuffer As Byte(), ByVal nPacketSize As Long)
End Sub


Public mydel As New CALLBACKdel(AddressOf CALLBACK)


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Dim Clientinfo As New CLIENT_VIDEOINFO()
    Clientinfo.m_bRemoteChannel = 0
    Clientinfo.m_bSendMode = 0
    Clientinfo.m_bImgFormat = 0
    Clientinfo.m_sIPAddress = "193.168.1.100"
    Clientinfo.m_sUserName = "1"
    Clientinfo.m_sUserPassword = "a"
    Clientinfo.m_bUserCheck = False
    Clientinfo.m_hShowVideo = Me.Handle 'Nothing


    MP4_ClientSetNetPort(850, 850)
    MP4_ClientStartup(WM_USER + 1, Me.Handle)

    MP4_ClientStart(Clientinfo, mydel)
End Sub

End Class


here is some other examples of the code in:

C#

http://blog.csdn.net/nenith1981/archive/2007/09/17/1787692.aspx

VB

://read.pudn.com/downloads70/sourcecode/graph/250633/MD%E5%AE%A2%E6%88%B7%E7%AB%AF%28VB%29/hikclient.bas__.htm

://read.pudn.com/downloads70/sourcecode/graph/250633/MD%E5%AE%A2%E6%88%B7%E7%AB%AF%28VB%29/Form1.frm__.htm

Delphi

://read.pudn.com/downloads91/sourcecode/multimedia/streaming/349759/Delphi_client/Unit1.pas__.htm

A: 

It's not a complete solution to your problem, but I'd start with adding StructLayoutAttribute(Sequential) to your Structure.

Imports System.Runtime.InteropServices

<StructLayout(LayoutKind.Sequential)> _
Public Structure CLIENT_VIDEOINFO
Mark Hurd
`LayoutKind.Sequential` should definitely be added, but it can’t be the cause of the error since this is actually what .NET uses by default (since at least .NET 2.0 AFAIK).
Konrad Rudolph
Interesting point. I'm sure I had code that failed until I put in an explicit LayoutKind.Sequential, however I have confirmed Sequential is the default even in 1.1.Note the VB Reference for Structure http://msdn.microsoft.com/en-us/library/k69kzbs1.aspximplies at Remarks > Behaviour > Memory Consumption that you do need to specify StructLayout to confirm the memory layout, but the documentation for StructLayoutAttributehttp://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute.aspxstates Sequential is the default for structures in Microsoft compilers.
Mark Hurd