CGO登录海康设备并使用Go1.17 unsafe包新特性

本文通过一个登录设备的例子,展示了如何在 Go 1.17 中使用 unsafe.Slice 方法。首先初始化 SDK,然后设置日志路径和设备路径。接着,创建登录信息并连接到设备,最后获取并打印设备信息,包括序列号、硬盘数等。示例中,使用了 C 库的接口和 Go 的 unsafe 包来操作内存。

本文通过一个常用的登录设备的例子,演示学习go1.17 unsafe.Slice方法的使用。具体例子如下:

package main

/*
#cgo CFLAGS: -I./libs/hiksdk-6.1.4.51/include/
#cgo LDFLAGS: -L./libs/hiksdk-6.1.4.51/lib/ -lHCCore -lhcnetsdk

#include "HCNetSDK.h"
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
*/
import "C"
import (
	"fmt"
	"reflect"
	"unsafe"
)

type NET_DVR_LOCAL_SDK_PATH struct {
	Path [256]byte
	Res  [128]byte
}

func main() {
	ret := C.NET_DVR_Init()
	if int(ret) != 1 {
		fmt.Printf("NET_DVR_Init failed,error code = %v\n", C.NET_DVR_GetLastError())
		return
	}
	defer C.NET_DVR_Cleanup()

	// 开启调试日志,不开启可以注掉,sdk的日志能看到详细的错误信息
	logPath := "/tmp"
	C.NET_DVR_SetLogToFile(3, C.CString(logPath), 1)

	// 如果动态库加载失败,可调用SDK手动设置海康动态库的路径,不设置可以注掉,如果加载不成功,尝试显示设置下
	var comPath = NET_DVR_LOCAL_SDK_PATH{}
	copy(comPath.Path[:], "/root/script/src/nvr/libs/hiksdk-6.1.4.51/lib/")
	C.NET_DVR_SetSDKInitCfg(C.NET_SDK_INIT_CFG_SDK_PATH, unsafe.Pointer(&comPath))

	var userLoginInfo C.NET_DVR_USER_LOGIN_INFO
	var deviceInfo C.NET_DVR_DEVICEINFO_V40

	userLoginInfo.wPort = 8000 // your device port,default 8000

	username := "your device username"
	// 转换成C字节数组
	pUsername := C.CBytes([]byte(username))
	defer C.free(pUsername)
	// 使用memcpy函数进行拷贝
	C.memcpy(unsafe.Pointer(&userLoginInfo.sUserName), pUsername, C.ulong(len(username)))

	password := "you device password"
	pPassword := C.CBytes([]byte(password))
	defer C.free(pPassword)
	C.memcpy(unsafe.Pointer(&userLoginInfo.sPassword), pPassword, C.ulong(len(password)))

	deviceIp := "your device ip"
	pDeviceIp := C.CBytes([]byte(deviceIp))
	defer C.free(pDeviceIp)
	C.memcpy(unsafe.Pointer(&userLoginInfo.sDeviceAddress), pDeviceIp, C.ulong(len(deviceIp)))

	// 调用登录接口
	loginId := C.NET_DVR_Login_V40((C.LPNET_DVR_USER_LOGIN_INFO)(&userLoginInfo), (C.LPNET_DVR_DEVICEINFO_V40)(&deviceInfo))
	if int32(loginId) < 0 {
		fmt.Printf("NET_DVR_Login_V40 failed,error code = %v", C.NET_DVR_GetLastError())
		return
	}

	byIPChanNum := uint8(deviceInfo.struDeviceV30.byIPChanNum)
	byHighDChanNum := uint8(deviceInfo.struDeviceV30.byHighDChanNum)

	// go1.17 unsafe.Slice 从给定的地址和长度产生一个任意类型的切片,须保证在使用中地址不能被释放
	// 下面参数中的地址未C内存结构的数字第一个元素的地址
	serialNo := unsafe.Slice((*byte)(unsafe.Pointer(&deviceInfo.struDeviceV30.sSerialNumber[0])), int(C.SERIALNO_LEN))

	fmt.Printf("用户ID:%d\n", int32(loginId))
	fmt.Printf("序列号:%s\n", string(serialNo))
	fmt.Printf("硬盘个数:%d\n", uint8(deviceInfo.struDeviceV30.byDiskNum))
	fmt.Printf("设备类型:%d\n", uint8(deviceInfo.struDeviceV30.byDVRType))
	fmt.Printf("设备模拟通道个数:%d\n", uint8(deviceInfo.struDeviceV30.byChanNum))
	fmt.Printf("设备模拟通道起始通道号:%d\n", uint8(deviceInfo.struDeviceV30.byStartChan))
	fmt.Printf("设备数字通道起始通道号:%d\n", uint8(deviceInfo.struDeviceV30.byStartDChan))
	fmt.Printf("设备IP通道个数:%d\n", uint16(byIPChanNum)+uint16(byHighDChanNum)*256)
}

运行结果如下:

用户ID:0
序列号:DS-删掉后面若干
硬盘个数:2
设备类型:90
设备模拟通道个数:0
设备模拟通道起始通道号:1
设备数字通道起始通道号:33
设备IP通道个数:16

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

空间法则

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值