laitimes

.NET calls the cross-platform solution of Hikvision SDK

  • 📢 Welcome to like: 👍 Collection ⭐ Message 📝 If there is a mistake, please correct, give people roses, and leave a lingering fragrance in your hands!
  • 📢 This article was written by webmote
  • 📢 Author's motto: The new journey, we are facing not only technology but also people's hearts, people's hearts are unpredictable, the sea water is immeasurable, only technology is a flickering beacon in the deep dark night

preface

The use of Hikvision SDK and common pits in the last 2 articles have been loved by many netizens, which also shows that in the field of industrial control, it is still very convenient to use .net development. The first version of the Net Framework version is published on github for testing and use.

This time I will mainly explain how to encapsulate Hikvision's cross-platform library when making cross-platform calls under .NET Core /6/7/8, after all, many R&D libraries have been migrated to .NET Core cross-platform systems in order to adapt to the trend of the times, support and compatibility with Linux systems, domestic operating systems or Huawei Hongmeng systems, etc.

.NET calls the cross-platform solution of Hikvision SDK

Under the statement, Hikvision did not give a sponsorship fee, I hope the manufacturer can see it and give a reward, haha~~~

1. Cross-platform library support

Currently, .NET Core supports two modes for loading class libraries, one is the traditional way, used

DllImport

attribute schema definition; The other is a new way to adopt

NativeLibrary

Advanced parsing and loading of class libraries requires you to confirm your .NET library version, which needs to be supported (.NET Core 3.1 and .NET 5+).

2. Use the default DllImport mode to load

If you're using this pattern, you'll need to limit the path to the dll in most cases, so let's take a look at what is the default rule?

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

The above code implies the following rules:

When running on Windows, DLLs are searched in the following order:

  • HCNetSDK
  • HCNetSDK.dll if the library name doesn't already end with .dll or .exe)

When running on Linux or macOS, the runtime will attempt to add first

lib

and append the extension. On these OSs, try the library names in the following order:

  • HCNetSDK.so / - HCNetSDK.dylib
  • libHCNetSDK.so / libHCNetSDK.dylib1
  • HCNetSDK
  • libHCNetSDK1

Note that on these systems, names are case-sensitive.

Of course, if the library name starts with

.so

End or contain

.so.

, the search order will be different.

  • HCNetSDK.so.6
  • libHCNetSDK.so.61
  • HCNetSDK.so.6.so
  • libHCNetSDK.so.6.so1

3. NativeLibrary is used for advanced parsing

In the new version of the .NET framework, it provides a series of functions to support library loading:

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)
           

which is still utilized

DllImport

Define the name of the class library and then utilize it

DllImportResolver

Advanced parsing.

  • parameter

    assembly

    : The assembly for which the resolver has been registered.
  • parameter

    resolver

    : The resolver callback to be registered.

This callback function is a native library load function that is started when you first try to resolve an assembly. The caller of this method should register the resolver only for its own assembly. Only one resolver can be registered per assembly. Attempts to register the second resolver fail and are displayed

InvalidOperationException

The following is the cross-platform core code that encapsulates the Hikvision 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. Path organization of Hikvision DLLs

According to the above definition of analysis, we have customized the path to load the Hikvision DLL, so we need to put the DLL according to the content in the code, and the placement method is as follows.

.NET calls the cross-platform solution of Hikvision SDK
.NET calls the cross-platform solution of Hikvision SDK

In the project file of the class libraries, you need to add the processing definitions for these class libraries:

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

Don't lose the compiled dll and Hikvision's dll directories and files.

5. Summary

If you load a small number of DLL files, you can use the first solution to simply mark and deploy; If the DLLs involved are complex and need to be placed in different directories for call support, then the second way is more convenient and flexible to customize the control.

According to my view of Microsoft documentation, there is another way is the DllMap method, and then Mono is used a lot, using XML to define the mapping of dll, you can achieve a scheme similar to 2, xml is similar to the following definition, I have not tried this way, interested friends can try it.

<configuration>
<dllmap dll="OldLib" target="NewLib"/>
</configuration>
           
.NET calls the cross-platform solution of Hikvision SDK

I hope you find these presentations helpful.

Have you lost your studies?

👓 It's all favorited, do you still care about a comment?