CGO 涉及的数据类型转换包含一下内容:
- 数值类型
- 字符串和切片类型
- 结构体、联合体、枚举类型‘
- 数组类型
- 指针类型
- 数组和指针间的转换
- 切片和切片之间的转换
前面 3 个咱们在上一篇短文已经梳理到了,接下来继续
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5lP6xgbk-1660485524922)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f4f6b12f88ab4bc49ea9703737f3c624~tplv-k3u1fbpfcp-zoom-1.image)]
数组类型
C 语言里面:
- 数组
C 语言里面,数组名对应一个指针,指向特定类型特定长度的一段内存,但是这个指针不能被修改
C语言的字符串是一个char类型的数组,字符串的长度需要根据表示结尾的NULL字符的位置确定
- 字符串
是一个 char 类型的数组
- 切片
C 语言没有切片的概念
GO 语言里面:
- 数组
数组是一种值类型,而且数组的长度是数组类型的一个部分
- 字符串
就是一段长度确定的只读byte类型的内存
- 切片
是一个简单的动态数组
从上面我们可以看出来,C 语言 和 GO 语言的数组,切片,字符串的相互转换,就可以是指针和指针指向的内存长度的转换
CGO 官方给咱们提供了如下 5 个函数,用于 C 语言和 GO 语言互相转换:
- func C.CString(string) *C.char
C.CString
将传入的 go 字符串,克隆成一个 C 格式的字符串,克隆出来的字符串是使用 C 语言中 malloc 开辟出来的,因此我们用完了这个函数,需要手动去释放内存
- func C.CBytes([]byte) unsafe.Pointer
C.CBytes
用于将输入的 go byte 类型的数组(切片),克隆并转换成 C 语言的指针,指针的是一个数组,需要开辟空间,不用的时候,也是需要手动释放
- func C.GoString(*C.char) string
C.GoString
将 C 的字符串克隆成 GO 的 string , GO 里面自己会释放内存
- func C.GoStringN(*C.char, C.int) string
C.GoStringN
,将C 具体某个长度的字符串转换成 GO 的 string, GO 里面自己会释放内存
- func C.GoBytes(unsafe.Pointer, C.int) []byte
C.GoBytes
将 C 的数组,转换成 GO 的切片
小结:
上述一组官方提供的函数,GO 语言和 C 语言相互转换都是通过克隆的方式实现
GO 转 C
C 是通过 malloc 的方式 在 C 自己的空间中开辟内存,因此我们不需要使用的时候,需要释放
C 转 GO
也是通过克隆的方式,但是 GO 有自己的内存管理,不需要我们手动释放内存
上述函数的优势
- 以克隆的方式进行转换,内存都是在各自语言内开辟的,内存管理简单
上述函数的劣势
- 相互转换都需要额外开辟内存,增大了系统开销
指针和指针间的转换
在 cgo 里面,如何实现指针和指针间的转换呢?
C 语言里面:
指针是 C 语言的灵魂,C 语言里面,不同类型指针间可以强制转换,指针间的自由转换也是 cgo 代码中经常要解决的第一个重要的问题
GO 语言里面:
不同类型的转换非常严格,任何 C 语言中可能出现的警告信息在Go语言中都可能是错误。
GO 里面不同类型的指针是禁止转换的,但是有了 CGO 就打破了这种禁锢