概述
cgo作为一个强大的工具,可以让go轻松实现调用c语言的巨额遗产。。。
问题
实际开发中,发现使用go语言调用c的动态库时,经常出现传入c的字符串发生变化的现象,如下:
-
情况1
由a.txt变为a.txt$\n -
情况2
由plain-0变为plain-0!
问题原因
最终发现是由于go与c字符串不同导致的,c语言的字符串默认以00000000结尾,而go没有这个规定,所以使用C.CBytes转换之后,传入c,c在解析成字符时发生了偏差。
解决方法
- 1、尽量遵循cgo规定的数据类型转换方法
// Go 字符串转换为 C 字符串
// C 字符串使用 malloc 来分配到 C 堆里。
// 调用方需要把它释放掉,比如调用 C.free (如果需要 C.free,确保程序包含 stdlib.h)
func C.CString(string) *C.char// 这里同样需要使用C.free释放内存
func C.CBytes([]byte) unsafe.Pointer// C 字符串转换为 Go 字符串
func C.GoString(*C.char) string// 有明确长度的 C 数据转换为 Go 字符串
func C.GoStringN(*C.char, C.int) string// 有明确长度的 C 数据转换为 Go []byte
func C.GoBytes(unsafe.Pointer, C.int) []byte
- 2、尽量避免直接将go指针传递给c使用,背离了Go语言的设计理念,容易出现问题
- 3、C.CString C.CBytes,是调用c开辟的内存空间,需要使用c.free进行内存释放
补充
GO 语言中访问 C 语言的 struct ,union,enum,数值类型对应关系:
参考
- https://v2ex.com/t/611625 (go与c的字符串不同讲解)
- https://juejin.cn/post/7158995386034552863
- http://westfly.github.io/post/cpp/cgo-with-cpp/
- https://mp.weixin.qq.com/s/I9IvJnKeJY8IpVB4lcWXNA(赞)
- https://github.com/andreiavrammsd/cgo-examples
- https://github.com/miekg/unbound/blob/master/unbound.go (unbound调用c)