.net 调用海康SDK以及常见的坑解释

  • 📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!

  • 📢本文作者:由webmote 原创

  • 📢作者格言:新的征程,我们面对的不仅仅是技术还有人心,人心不可测,海水不可量,唯有技术,才是深沉黑夜中的一座闪烁的灯塔 !

序言

在工控领域,很多时候需要访问和控制海康相机,通过程序控制海康相机可以实现变倍变焦,拍照,抓取视频等不同的操作。海康的SDK是C++编写的Dll,因为没有很好的进行包装,使用起来还是比较麻烦的,并且随着海康SDK的版本不同,各类版本有许多差异性,不好的封装会导致有很多的问题,这里把踩过的坑列举下,以便后来者少踩坑。

e17596e0c05d452ed4e86dc8f74d54bc.png

1. 一个进程只能加在一个海康DLL

在许多的应用中,有时候会不小心有多个类库,如果重复引用了海康DLL,会导致C#在调用海康威视CHCNetSDK出现未能从程序集中加载类型“WIFI_AUTH_PARAM”,因为它在 0 偏移位置处包含一个对象字段,该字段已由一个非对象字段不正确地对齐或重叠。

很多的处理方案是把整个文件接口体头部的LayoutKind.Explicit改为LayoutKind.Auto,删除所有[FieldOffset(0)],这个从语言体系上来说是错误的,但方法又是可行的,为啥?

根本原因是你没有用到此结构体而已,一旦有引用,那么很可能带来不必要的麻烦。

因此,出现问题不要慌,仔细查找相关库,是不是有多次引用海康库的问题,就可以从根本上解决该问题。

2.监测海康相机是否还在线,或登录过期

很多同学采用ping方式进行监测,不得不说,这是最初级的方案,它根本无法检测登录过期问题,正确的做法是利用SDK中的使用userid的函数,我这里挑了个简单的方法进行检测,非常好用,大家不妨拿来用:

public bool CheckDevice(int userId)
 {
     IntPtr addr = IntPtr.Zero;
     uint nOutSize = 0;
     try
     {
         int nInSize = Marshal.SizeOf<CHCNetSDK.NET_DVR_TIME>();
         addr = Marshal.AllocHGlobal(nInSize);
         var rtn = CHCNetSDK.NET_DVR_GetDVRConfig(userId, CHCNetSDK.NET_DVR_GET_TIMECFG, 0, addr, (uint)nInSize, ref nOutSize);
         var dvrTime = Marshal.PtrToStructure<CHCNetSDK.NET_DVR_TIME>(addr);
         return rtn;
     }
     catch
     {
         return false;
     }
     finally
     {
         if (addr != IntPtr.Zero)
         {
             try
             {
                 Marshal.FreeHGlobal(addr);
             }
             catch { }
         }
     }
 }

利用CheckDevice函数,就可以对海康设备的通断情况进行直接检测,不但效率比ping高,而且可靠易用。

3. 海康DLL引用

引用有几种方式,最简单的方式是直接使用 DllImportAttribute属性进行,简单方便,只需要记得把海康的dll文件放在执行根目录的相对路径下即可。

[DllImport(@"\HkSdk\HCNetSDK.dll")]
 public static extern bool NET_DVR_STDXMLConfig(int iUserID, ref NET_DVR_XML_CONFIG_INPUT lpInputParam, ref NET_DVR_XML_CONFIG_OUTPUT lpOutputParam);
 ...
 //这个文件应该都有吧...
  public class CHCNetSDK
 {
     public CHCNetSDK()
     {
         //
         // TODO: 在此处添加构造函数逻辑
         //
     }

     //2019 3.1添加
     [StructLayoutAttribute(LayoutKind.Sequential)]
     public struct NET_DVR_XML_CONFIG_INPUT
     {
         public uint dwSize;//结构体大小 
         public IntPtr lpRequestUrl;//请求信令,字符串格式 
         public uint dwRequestUrlLen;
         public IntPtr lpInBuffer;//输入参数缓冲区,XML格式 
         public uint dwInBufferSize;
         public uint dwRecvTimeOut;//接收超时时间,单位:ms,填0则使用默认超时5s 
         [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.I1)]
         public byte[] byRes;
     }

     [StructLayoutAttribute(LayoutKind.Sequential)]
     public struct NET_DVR_XML_CONFIG_OUTPUT
     {
         public uint dwSize;//结构体大小 
         public IntPtr lpOutBuffer;//输出参数缓冲区,XML格式 
         public uint dwOutBufferSize;
         public uint dwReturnedXMLSize;//实际输出的XML内容大小 
         public IntPtr lpStatusBuffer;//返回的状态参数(XML格式:ResponseStatus),获取命令成功时不会赋值,如果不需要,可以置NULL 
         public uint dwStatusSize;//状态缓冲区大小(内存大小) 
         [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.I1)]
         public byte[] byRes;
     }
 }

还有如果需要支持linux平台,以及windows的x86和x64,那么需要更多的封装,如果有需要可以留言。

4. SDK的初始化

海康SDK在使用的时候,需要进行SDK的初始化,在退出时,需要销毁资源,这里的资源属于非托管资源,因此请谨慎反复调用。

CHCNetSDK.NET_DVR_Cleanup();
if (!CHCNetSDK.NET_DVR_Init())
{
    throw new Exception("海康相机初始化失败:调用NET_DVR_Init()方法返回false");
}

5. 登录登出

海康SDK支持限定并发连接到海康设备,因此频繁登入可能导致46错误,我们使用的时候,记得配对使用,避免引入bug。

var userID = CHCNetSDK.NET_DVR_Login_V40(ref struLogInfo, ref deviceInfo);
HCNetSDK.NET_DVR_Logout_V30(userID);

6.错误解析和输出

像大多数c++类库一样,它们都是采用一个特定函数获取错误码的。

public  string GetErrorDetail()
{
    var errorCode = CHCNetSDK.NET_DVR_GetLastError();
    LastErrorCode = errorCode;
    return string.Format("错误码:{0}", errorCode);
}

7.结论

我这里没有提供封装好的类库,这应该是有大量需求的,海康自己也没有很好的进行封装,我计划后面会提供一个,先发文章看看是否有需求了,大家可以评论给我。

你学废了吗?

👓都看到这了,还在乎点个赞吗?

👓都点赞了,还在乎一个收藏吗?

👓都收藏了,还在乎一个评论吗?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值