1

我正在尝试使用海康威视 SDK https://www.hikvision.com/en/support/download/sdk/ 我目前的目标是打开对讲室外站的门(触发输出)。

我设法登录(NET_DVR_LoginV40)并显示室外站的摄像头。

我的下一步是开门。为此,我需要调用 NET_DVR_RemoteControl 函数,其中包括 NET_DVR_Control_GateWay 的结构。

现在这样做时它不起作用,它返回错误 17,这显然是:

参数错误。SDK API中的输入或输出参数为NULL,或参数的值或格式与需求不匹配。

因此,我的 C# 代码中几乎 100% 有问题。但我不知道它是什么,据我所知,如果您不是这方面的专家(我不是),这很难轻易确定

函数的 dll 导入:

[DllImport(@"..\bin\HCNetSDK.dll")]
public static extern bool NET_DVR_RemoteControl(int lUserID, uint dwCommand, IntPtr lpInBuffer, uint dwInBufferSize);

上一个函数的参数结构:

 [StructLayoutAttribute(LayoutKind.Sequential)]
        public struct NET_DVR_Control_GateWay
        {
            public uint dwSize;
            public uint dwGatewayIndex;
            public byte byCommand;
            public byte byLockType;
            public UInt16 wLockID;
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.I1)]
            public byte[] byControlSrc;
            public byte byControlType;
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I1)]
            public byte[] byRes3;
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 16, ArraySubType = UnmanagedType.I1)]
            public byte[] byPassword;
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 108, ArraySubType = UnmanagedType.I1)]
            public byte[] byRes2;
            public void Init()
            {
                byRes3 = new byte[64];
                byRes2 = new byte[108];
            }
        }

我的开门方法:

 private void button_Door1_Click(object sender, EventArgs e)
        {
            CHCNetSDK.NET_DVR_Control_GateWay gateWay = new CHCNetSDK.NET_DVR_Control_GateWay();
            gateWay.Init();
            gateWay.dwSize = (uint)Marshal.SizeOf(gateWay);
            gateWay.dwGatewayIndex = 1;
            gateWay.byCommand =1; //opening command
            gateWay.byLockType =  0 ; //this is a normal lock not a smart lock
            gateWay.wLockID = 0; //this is 0 because I want to use the door station's output
            gateWay.byControlSrc =  new byte[] {123} ; // this needs to be something, but doesn't matter what
            gateWay.byControlType =  1 ; //this needs to be 1 or 2 but does not matter which
            //gateWay.byPassword = ; this is not needed because the LockType is 0
            IntPtr ptrStruData = Marshal.AllocHGlobal((int)gateWay.dwSize);
            var dd = CHCNetSDK.NET_DVR_RemoteControl(lUserID, 16009, ptrStruData, gateWay.dwSize);
           
            MessageBox.Show(dd.ToString() + CHCNetSDK.NET_DVR_GetLastError().ToString() + "\n" + gateWay.dwSize.ToString() + "\n" + "ptrStruData:" + ptrStruData.ToString());
        }

根据文档,函数看起来像这样

结构是这样定义的

因此,据我所知,我已经正确完成了定义和导入。

如果有人能让我朝着正确的方向前进,我将不胜感激,因为我之前从未使用过 C#、c++ 互操作,此时我不知道如何前进,如何调试,如何确定代码中的问题.

我已尝试就此问题与制造商联系,但他们无法直接帮助我处理代码,并且从他们的角度来看,一切正常,因为我得到了错误,即问题的原因是我。

非常感谢您的帮助!

4

1 回答 1

1

您使用 分配一些内存Marshal.AllocHGlobal,不将gateWay结构复制到该内存中,将指针传递给分配的内存,NET_DVR_RemoteControl以便它看到随机垃圾,然后您不释放分配的内存以使其泄漏。

您可以通过复制 gateWay到分配的内存然后在调用后释放它来修复它。

然而,最好让编组器完成它的工作:

[DllImport(HIKVISION_LIBRARY, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = false)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool NET_DVR_RemoteControl(int lUserID, int dwCommand, [In] ref NET_DVR_CONTROL_GATEWAY lpInBuffer, int dwInBufferSize);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct NET_DVR_CONTROL_GATEWAY
{
    public int dwSize;
    public int dwGatewayIndex;
    public byte byCommand;
    public byte byLockType;
    public short wLockID;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NAME_LEN)]
    public string byControlSrc;

    public byte byControlType;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public byte[] byRes3;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = PASSWD_LEN)]
    public string byPassword;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 108)]
    public byte[] byRes2;
}
var gateWay = new NET_DVR_CONTROL_GATEWAY()
{
    dwSize = Marshal.SizeOf<NET_DVR_CONTROL_GATEWAY>(),
    dwGatewayIndex = 1,
    byCommand = 1,
    byLockType = 0,
    wLockID = 0,
    byControlType = 1
};

var dd = NET_DVR_RemoteControl(lUserID, 16009, ref gateWay, gateWay.dwSize);
于 2021-07-07T20:41:52.417 回答