.net 调用海康SDK的跨平台解决方案

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

  • 📢本文作者:由webmote 原创

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

序言

上2篇海康SDK使用以及常见的坑受到了许多网友的喜爱,这也说明了在工控领域内,使用.net开发还是非常便捷省事的。针对海康的SDK进行进一步封装,第一版Net Framework版本代码发在github上,供大家测试和使用。

这次主要讲解在.net core /6/7/8下进行跨平台调用时怎么封装海康的跨平台库,毕竟很多的研发类库已经都迁移到.net core 跨平台的系统上,以便适应时代的潮流,支持和兼容linux系统,国产操作系统或者华为鸿蒙系统等。
20e0d9c86fea39c5473733341b82b100.png

声明下,海康威视没有给赞助费,希望厂家能够看到,给点打赏,哈哈~~~

1. 跨平台类库支持

目前.net Core 支持两种模式对类库进行加载,一种是传统方式,使用DllImport属性模式定义;另外一种是新的方式,采用NativeLibrary类库进行高级解析和加载,这种方式需要你确认你的.net 类库版本,需要在支持范围内(.net core 3.1 以及.net 5+)。

2. 采用DllImport默认方式加载

如果你使用这种模式,那么大部分情形需要限定dll的路径,因此我们先看下默认采用的规则是什么?

[DllImport("HCNetSDK")]
public static extern bool NET_DVR_Init();

上面的代码,就隐含了下列规则:
在 Windows 上运行时,将按以下顺序搜索 DLL:

  • HCNetSDK

  • HCNetSDK.dll(如果库名称尚未以 .dll 或 .exe 结尾)

在 Linux 或 macOS 上运行时,运行时将尝试在前添加 lib ,并追加扩展名。在这些 OS 上,按以下顺序尝试库名:

  • HCNetSDK.so / - HCNetSDK.dylib

  • libHCNetSDK.so / libHCNetSDK.dylib1

  • HCNetSDK

  • libHCNetSDK1

注意,在这些系统上,名称是区分大小写的。

当然,如果类库名称以.so结尾或包含.so. ,则搜索顺序会有所不同。

  • HCNetSDK.so.6

  • libHCNetSDK.so.61

  • HCNetSDK.so.6.so

  • libHCNetSDK.so.6.so1

3.采用NativeLibrary进行高级解析

在新版本的.net框架中,其提供了一系列函数对库加载的支持:

void Free(IntPtr handle)
IntPtr GetExport(IntPtr handle, String name)
IntPtr Load(String libraryPath)
IntPtr Load(String libraryName, Assembly, DllImportSearchPath?)
void SetDllImportResolver(Assembly, DllImportResolver)
IntPtr TryGetExport(IntPtr handle, String name, out IntPtr address)
IntPtr TryLoad(String libraryPath, out IntPtr handle)
IntPtr TryLoad(String libraryName, Assembly, DllImportSearchPath?, out IntPtr handle)

其中仍然利用DllImport界定类库名称,然后再利用DllImportResolver进行高级解析。

  • 参数assembly:已为其注册解析程序的程序集。

  • 参数 resolver:要注册的解析程序回调。

此回调函数是第一次尝试解析程序集时启动的本机库加载函数。此方法的调用方应仅为自己的程序集注册解析程序。每个程序集只能注册一个解析程序。尝试注册第二个解析程序失败,并显示 InvalidOperationException

以下是封装海康SDK的跨平台核心代码:

public class HcNetSdk
 {
     private const string HCNetSDK = "HCNetSDK";    
     //静态构造,保调用时,一次加载。
     static HcNetSdk()
     {
         NativeLibrary.SetDllImportResolver(typeof(HcNetSdk).Assembly, DllImportResolver);
     }
     private static IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
     {
         // windows下加载dll
         if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
         {
             if (Environment.Is64BitProcess)
             {
                 if (libraryName == HCNetSDK)
                 {
                     return NativeLibrary.Load("./HCNetSDK/x64/HCNetSDK.dll", assembly, searchPath);
                 }
                 else if(libraryName == AnalyzeData)
                 {
                     return NativeLibrary.Load("./HCNetSDK/x64/HCNetSDKCom/AnalyzeData.dll", assembly, searchPath);
                 }
             }
             else
             {
                 if (libraryName == HCNetSDK)
                 {
                     return NativeLibrary.Load("./HCNetSDK/x86/HCNetSDK.dll", assembly, searchPath);
                 }
                 else if (libraryName == AnalyzeData)
                 {
                     return NativeLibrary.Load("./HCNetSDK/x86/HCNetSDKCom/AnalyzeData.dll", assembly, searchPath);
                 }
             }                
         }
         else //linux操作系统下,此处没有细分,如果有更多系统需求,可以自行增加
         {
             if (libraryName == HCNetSDK)
             {
                 return NativeLibrary.Load("./HCNetSDK/linux/libhcnetsdk.so", assembly, searchPath);
             }
             else if (libraryName == AnalyzeData)
             {
                 return NativeLibrary.Load("./HCNetSDK/linux/HCNetSDKCom/libanalyzedata.so", assembly, searchPath);
             }
         }
         

         // Otherwise, fallback to default import resolver.
         return IntPtr.Zero;
     }
    
     public HcNetSdk()
     {
         //
         // TODO: 在此处添加构造函数逻辑
         //
     }
     [DllImport(HCNetSDK)]
	public static extern int NET_DVR_SendWithRecvRemoteConfig(int lHandle, IntPtr lpInBuff, uint dwInBuffSize, IntPtr lpOutBuff, uint dwOutBuffSize, ref uint dwOutDataLen);
	
	[DllImport(HCNetSDK)]
	public static extern int NET_DVR_SendWithRecvRemoteConfig(int lHandle, ref HcNetSdk.NET_DVR_FACE_RECORD lpInBuff, int dwInBuffSize, ref HcNetSdk.NET_DVR_FACE_STATUS lpOutBuff, int dwOutBuffSize, IntPtr dwOutDataLen);
	
	[DllImport(HCNetSDK)]
	public static extern int NET_DVR_SendWithRecvRemoteConfig(int lHandle, ref HcNetSdk.NET_DVR_FINGERPRINT_RECORD lpInBuff, int dwInBuffSize, ref HcNetSdk.NET_DVR_FINGERPRINT_STATUS lpOutBuff, int dwOutBuffSize, IntPtr dwOutDataLen);
...
}

4. 海康dll的路径组织

按照上面的解析定义,我们自定义了路径进行海康dll的加载,因此需要按照代码内的内容对dll及放好,放置方式如下所示。
183a43d17ef023fe4bb3900272f73765.png
fb718b414dd711572763aceea817e7bb.png

类库的项目文件中,需要增加对这些类库的处理定义:

<ItemGroup>
  <None Update="HCNetSDK\**">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </None>
</ItemGroup>

编译的dll 和海康的dll目录和文件不要搞丢了。

5. 总结

这里以海康sdk的dll加载为例,介绍了两种方案进行跨平台的封装方式,如果你加载的dll文件比较少,可以使用第一种方案简单的进行标记和部署即可;如果涉及的dll比较复杂,需要放在不同的目录下进行调用支撑,那么采用第二种方式自定义控制更方便灵活。

据我查看微软文档,还有一种方式是DllMap方式,再Mono下用的非常多,采用XML方式对dll的映射进行定义,即可实现类似2的方案,xml类似如下定义,这种方式我没有试过,有兴趣的朋友可以试一试。

<configuration>
    <dllmap dll="OldLib" target="NewLib"/>
</configuration>

5dd7d306846e750cc87cc03cf0a20ee1.png

希望这些介绍能帮助到大家。

你学废了吗?

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

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

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

设备网络SDK是基于设备私有网络通信协议开发的,为后端设备(嵌入式网络硬盘录像机、视频服务器)、前端设备(网络摄像机、网络球机、IP模块)等产品服务的配套模块,用于远程访问和控制设备软件的二次开发。 适用于以下产品型号: DS-95xx、DS-96xxNVR; DS-90xx混合型硬盘录像机; DS-91xx、DS-81xx、DS-80xx、DS-70xx、DS-71xx、DS-7116、DS-72xx硬盘录像机; DS-60xx、DS-61xx视频服务器、编/解码器; iDS-6002HF/B双摄像机跟踪、iDS-6101HF智能设备(行为分析)、iDS52xx智能分析仪、iDS90XX、iDS91XX; DS630x_D、DS-6401HD多路解码器; IP摄像机(以下简称“IPC”):DS-2CD71xx、DS-2CD81xx、DS-2CD7xx、DS-2CD8xx、DS-2CD9xx; 其他IP设备:包含IP模块、IP快球等。 由于某些功能在此SDK版本中做了扩展,同时设备程序也做了相应的更新扩展,为了方便下文说明,此处将以上设备归为两类:如DS-7116、DS-81xx、DS-90xx、DS-91xx、DS-95xx、DS-96xx等系列设备称为V3.0以上版本支持的设备;如DS-80xx、IPC等设备称为V3.0以下版本支持的设备。 设备网络SDK主要功能 图像预览、文件回放和下载、云台控制、布防/撤防、语音对讲、日志管理、解码卡、远程升级、远程重启/关闭、格式化硬盘、参数配置(系统配置、通道配置、串口配置、报警配置、用户配置)、多路解码器、智能设备功能和获取设备能力集等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值