CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9

Hybrid View

  1. #1
    Join Date
    Nov 2013
    Location
    Milan [.NET 4.5]
    Posts
    17

    [RESOLVED] Wrapper from C++ to C#

    Hi all,


    I'm Marco and I'm a .NET software developer. I'm developing a C# console application based on a C++ set of DLLs using the DllImport attribute.

    The C++ DLLs are part of a Video Management System SDK developed by a third part.

    Following you'll find a piece of code that I wrote but that's not work properly:


    Code:
    [DllImport("TruVNetSDK.dll")]
    public static extern int NET_DVR_Login_V30(string sDVRIP, int wDVRPort, string sUserName, string sPassword, out LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo);
    
    public struct LPNET_DVR_DEVICEINFO_V30
    {
    
    public byte sSerialNumber; public byte byAlarmInPortNum; public byte byAlarmOutPortNum; public byte byDiskNum; public byte byChanNum; public byte byStartChan;
    } public void LogOn() {
    LPNET_DVR_DEVICEINFO_V30 _info; NET_DVR_Login_V30("ip_address", port_number, "username", "password", out _info);
    }
    And following the documentation provided by the third part developer team about the "NET_DVR_Login_V30" function and the "LPNET_DVR_DEVICEINFO_V30" struct:

    LONG NET_DVR_Login_V30 (char *sDVRIP, WORD wDVRPort, char *sUserName, char *sPassword, LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo)
    Parameters:
    sDVRIP
    [in] IP address of the DVR
    wServerPort
    [in] Port NO. of the DVR
    sUserName
    [in] User's name
    sPassword
    [in] Password
    lpDeviceInfo
    [out] Information of device


    struct{
    BYTE sSerialNumber[SERIALNO_LEN];
    BYTE byAlarmInPortNum;
    BYTE byAlarmOutPortNum;
    BYTE byDiskNum;
    BYTE byChanNum;
    BYTE byStartChan;
    }NET_DVR_DEVICEINFO,*LPNET_DVR_DEVICEINFO;

    Members:
    sSerialNumber
    Serial NO.
    byAlarmInPortNum
    The number of alarm input
    byAlarmOutPortNum
    The number of alarm output
    byDiskNum
    The number of hard disks
    byChanNum
    The number of analog channels
    byStartChan
    Start number of channel, start from 1 currently.

    The problem is that I don't understand what kind of values are stored in the "_info" struct:

    _info.sSerialNumber = 86
    _info.byAlarmInPortNum = 82
    _info.byAlarmOutPortNum = 48
    _info.byDiskNum = 49
    _info.byChanNum = 56
    _info.byStartChan = 84


    These values are not correct, the real values should be:

    TVR11080820121218BBRR090016095WCVU
    4
    1
    1
    8
    1


    What's wrong?


    Thank you a lot

  2. #2
    Join Date
    May 2002
    Posts
    511

    Re: Wrapper from C++ to C#

    You need to change your marshalling a bit.

    Code:
    public static extern int NET_DVR_Login_V30(string sDVRIP, int wDVRPort, string sUserName, string sPassword, out LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo);
    
    public struct LPNET_DVR_DEVICEINFO_V30
    {
    public byte sSerialNumber;
    public byte byAlarmInPortNum;
    public byte byAlarmOutPortNum;
    public byte byDiskNum;
    public byte byChanNum;
    public byte byStartChan;}
    Should be something more like:

    Code:
    public static extern int NET_DVR_Login_V30([In][MarshalAs(UnmanagedType.LPWStr)] string sDVRIP, int wDVRPort, [In][MarshalAs(UnmanagedType.LPWStr)] string sUserName, [In][MarshalAs(UnmanagedType.LPWStr)] string sPassword, ref LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo);
    
    public struct LPNET_DVR_DEVICEINFO_V30
    {
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] // set to SERIALNO_LEN
    public string sSerialNumber;
    [MarshalAs(UnmanagedType.U1)]
    public byte byAlarmInPortNum;
    [MarshalAs(UnmanagedType.U1)]
    public byte byAlarmOutPortNum;
    [MarshalAs(UnmanagedType.U1)]
    public byte byDiskNum;
    [MarshalAs(UnmanagedType.U1)]
    public byte byChanNum;
    [MarshalAs(UnmanagedType.U1)]
    public byte byStartChan;}

  3. #3
    Join Date
    Nov 2013
    Location
    Milan [.NET 4.5]
    Posts
    17

    Re: Wrapper from C++ to C#

    Great Tron it's working!

    I think that I will study the MarshalAs attribute

  4. #4
    Join Date
    Nov 2013
    Location
    Milan [.NET 4.5]
    Posts
    17

    Re: Wrapper from C++ to C#

    Hi guys,


    now I'm struggling to make work properly another function, following my piece of code:


    Code:
    [DllImport("TruVNetSDK.dll")]
    public static extern bool NET_DVR_CaptureJPEGPicture(int lUserID, int lChannel, LPNET_DVR_JPEGPARA lpJpegPara, [In][MarshalAs(UnmanagedType.LPWStr)] string sPicFileName);
    
    public struct LPNET_DVR_JPEGPARA
    {
    
    [MarshalAs(UnmanagedType.U2)] public ushort wPicSize; [MarshalAs(UnmanagedType.U2)] public ushort wPicQuality;
    } public bool CaptureJPEGPicture(int userId, int channelNumber) {
    LPNET_DVR_JPEGPARA param = new LPNET_DVR_JPEGPARA(); param.wPicSize = 0; // VGA param.wPicQuality = 2; // best quality return NET_DVR_CaptureJPEGPicture(userId, channelNumber, param, "D:\test.jpeg");
    }

    Following the SDK documentation:

    BOOL NET_DVR_CaptureJPEGPicture(LONG lUserID, LONG lChannel, LPNET_DVR_JPEGPARA lpJpegPara, char *sPicFileName)
    Parameters:
    lUserID
    [in] The return value of NET_DVR_Login_V30
    lChannel
    [in] Channel number
    lpJpegPara
    [in] JPEG image parameter
    sPicFileName
    [in] URL of JPEG file

    Structure of JPEG picture parameters
    struct{
    WORD wPicSize;
    WORD wPicQuality;
    }NET_DVR_JPEGPARA,*LPNET_DVR_JPEGPARA;

    Members
    wPicSize
    Size of picture: 0-CIF, 1-QCIF, 2-D1, 3-UXGA, 4-SVGA, 5-HD720p, 6-VGA, 7-XVGA, 8-HD900p, 9-HD1080, 10-2560*1920, 11-1600*304, 12-2048*1536, 13-2448*2048
    wPicQuality
    Picture quality: 0- best, 1- better, 2- average

    When I call CaptureJPEGPicture() an exception is thrown:

    "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."


    Why this error?


    Thank you a lot!

    Marco

  5. #5
    Join Date
    May 2002
    Posts
    511

    Re: Wrapper from C++ to C#

    The first method works because you are receiving the structure from the API so a pointer will do the trick.

    To send structures to the API you'll have to do more.

    Something like this:

    Code:
                    IntPtr pStruct = Marshal.AllocCoTaskMem(structureSize);
                    if (null != pStruct )
                    {
                        Marshal.Copy(myStruct, 0, pStruct , structureSize);
    
                        // use pStruct
    
                        Marshal.FreeCoTaskMem(pStruct);
                    }

  6. #6
    Join Date
    May 2002
    Posts
    511

    Re: Wrapper from C++ to C#

    Actually in your case you most likely need the following line instead of Marshal.Copy().

    Code:
    Marshal.StructureToPtr(myStruct, pStruct, false)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured