Golang使用海康威视SDK
source link: https://hkvision.cn/2019/09/13/golang%E4%BD%BF%E7%94%A8%E6%B5%B7%E5%BA%B7%E5%A8%81%E8%A7%86sdk/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Golang使用海康威视SDK
2019年9月13日本文为原创文章,转载注明出处,欢迎关注网站https://hkvision.cn
接上一篇文章SWIG编译海康威视SDK-使用golang,这篇文章讲述的是如何使用编译好的文件,这涉及到SWIG和golang结合的问题
编译好了之后.a
文件会出现在GOPATH
下,直接在import里面引入hikvision
就可以了,build的时候会自动找到对应的.a
文件
下面从两个方面来介绍
- golang中已有的类型对应关系
- C里面
typedef
的值的对应关系,例如海康威视有BOOL
,DWORD
等
golang中已有的类型对应关系
这里说的已有的类型是指在C语言中已经有了,比如说int,char*等,具体的对应关系表网上有很多,SWIG在这里的策略和cgo
是一样的,这里给一个链接。这里就不多说了,在函数调用的时候可以直接把对应的go值传进去而不需要转换
C里面typedef
的值的对应关系
这里主要来说这个问题
由于海康威视的SDK大量使用了typedef
(应该是为了解决跨平台编译的问题),导致很多函数的返回值,参数值都不是正常的C类型,再加上大量的结构体,像我这样的菜鸟一开始根本无从下手,后来仔细看了SWIG生成的wrapper
文件和搜索引擎了一番,才弄明白SWIG的逻辑。
SWIG的实现其实就是调用了cgo,只是他给你封装了一层,你如果弄明白了cgo的逻辑,那SWIG的逻辑也就不难理解了。
Swigcptr uintptr unsafe.Pointer
这是核心,这三个东西构成了所有的C和go直接的类型交互。首先介绍一下C和go之间进行参数传递的流程
G
cluster_go2c
Go to C
cluster_c2go
C to Go
a0
go值
a1
go野指针
a0->a1
unsafe.Pointer
a2
内存地址的uint值
a1->a2
uintptr
a3
C指针
a2->a3
Swigcptrxxx
b0
C指针
b1
内存地址的uint值
b0->b1
Swigcptr
b2
go野指针
b1->b2
unsafe.Pointer
b3
go值
b2->b3
指针转换
这里的Swigcpterxxx
后面的xxx
对应的类型名称,Swig会自动帮我们生成这个函数。
整个的核心在于unsafe.Pointer
函数,这个函数接收一个指针类型的变量(也可以接收uintptr
类型的值),输出的是一个指针,但是对于go来说,这个指针已经变成了类似于野指针的存在,也就是说go不再承认这个指针是go体系里面的内容,gc也不会回收这块内存,需要我们自行管理。这个指针和C里面的void指针类似,代表这个指针可以指向任何一块内存。因此可以将这个指针对应的uint值(内存地址都可以用uint类型的变量来存储,这是一个特殊的类型,在GO和C中是uintptr
,本质和uint是一样的)传递到C中。C的值传递到GO也是一样的过程,都是通过void*
类型和unsafe.Pointer
类型的值可以互传来实现的。
在海康威视的SDK中有一种类型本身就是指针,例如LPVOID
,那么使用SWIG编译后,对于GO程序而言,同样要用多重指针的思路来解决。
多重指针和单指针是一样的道理,在将GO值传递到C之前,我们首先要将这个值转化为多重指针,然后再进行上述步骤,这样海康威视SDK拿到的值才是正确的,不然就会报错。我也是实验了很多次才发现这个问题的,其实应该一开始就明白这个问题,还是基础不够扎实,没能一眼看明白。
下面是一个示例
lpOutBuffer_t := hk.NewNET_DVR_DIGITAL_CHANNEL_STATE()
defer hk.DeleteNET_DVR_DIGITAL_CHANNEL_STATE(lpOutBuffer_t)
dwCommand_t := hk.NET_DVR_GET_DIGITAL_CHANNEL_STATE
// 注意这里的转换与下面的转化的不同
lpOutBuffer_p := unsafe.Pointer(lpOutBuffer_t.Swigcptr())
lpOutBuffer := hk.SwigcptrLPVOID(uintptr(unsafe.Pointer(&lpOutBuffer_p)))
// 注意这里只用了一次`unsafe.Pointer`函数
dwCommand := hk.SwigcptrDWORD(uintptr(unsafe.Pointer(&dwCommand_t)))
这是截取的代码的一小部分,这里我是需要调用海康威视的NET_DVR_GetDVRConfig
函数,这个函数有一个参数即为LPVOID
类型,就是lpOutBuffer
这个变量,实际上这个变量的值类型是NET_DVR_DIGITAL_CHANNEL_STATE
,大家可以看到,这里首先在在创建一个NET_DVR_DIGITAL_CHANNEL_STATE
类型后,先用Swigcptr
函数拿到变量对应的地址,然后用两次unsafe.Pointer
函数,然后才转成LPVOID
,其余的变量我们只转换了一次。
函数调用非常简单,当我们用unsafe.Pointer
组织好各个参数后,直接调用即可,注意返回值也需要进行转换,这里就是进行逆转换了,对于海康威视SDK,大家可以写一个公共函数来进行转换,这样方便调用。
Recommend
-
61
solidot新版网站常见问题,请点击这里查看。 Solidot 公告
-
52
近日,美国商务部就解除对中兴公司的销售禁令通报美国国会。中兴事件基本告一段落。本以为国内有出口美国业务的公司暂时安全了,结果下一个行业的公司又遭殃了。美国众议院通过立法,以国家安全为名禁止美国政府购买中国的视频监控等产品。其中就有海康威视,大...
-
509
写在前面的话 我们经常在网上看到某某通用IP摄像机被黑客利用的新闻。大多数情况下,制造商并不会强制用户设置安全密码,通常您可以使用默认密码直接登录。但有些厂商与众不同——海康威视。首次登录时使用密码是 123...
-
44
安防行业并不只是投钱就能做得起来的,资本会有一时的冲动,但退出的速度也会很快。 ——胡扬忠 近两年,海康威视”莫名”成为...
-
61
程序员 - @HuasLeung - 传送门: https://www.toutiao.com/i6693661818667139587
-
13
-
30
本文来自全天候科技,阅读更多请登陆 www.awtmt.com 或华尔街见闻APP。 作者|张超 编辑|罗丽娟 “没有什么高大上,很土,就是找口饭吃。现在我们还是想着怎么继续活下去,继续有...
-
10
Ubuntu 16.04 x86_64 安装和部署 NFS 服务,并使用海思设备挂载到 Ubuntu 发表于...
-
7
本文为原创文章,转载注明出处,欢迎关注网站https://hkvision.cn先允许我吐槽一下海康威视的SDK有多难用SWIG编译先声明我编译的是linux版本的,环境是ubuntu 18.04,还没有开始做...
-
2
微星AM5平台为使用海力士A-Die颗粒的内存优化,将提升读写性能并降低延迟
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK