CGO 編程入門

這一期我們講一講 CGO 中關於 C 數組、字符串、指針等類型的轉換。

數組、字符串類型

學過 C 語言的都知道,數組名其實對應於一個指針,該指針指向某一類型的一段內存。而在 Go 語言中,數組是一種值類型,數組長度也是數組類型的一個部分。在 CGO 的 C 僞包中,有一組函數可以用於 Go 語言和 C 語言之間數組以及字符串之間的轉換:

// Go string to C string
// The C string is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CString(string) *C.char

// Go []byte slice to C array
// The C array is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CBytes([]byte) unsafe.Pointer

// C string to Go string
func C.GoString(*C.char) string

// C data with explicit length to Go string
func C.GoStringN(*C.char, C.int) string

// C data with explicit length to Go []byte
func C.GoBytes(unsafe.Pointer, C.int) []byte

C.CString 把 Go 語言字符串複製成爲一個 C 語言字符串,其字符串由 C 語言的 malloc 函數分配,不使用時需要通過 C 語言的 free 函數釋放。

C.CBytes 把 Go 語言字節切片複製成爲一個 C 語言字節數組,其返回的數組需要在合適的時候釋放。

C.GoString 把 C 語言字符串複製成爲一個 Go 語言字符串。

C.GoStringN 同樣是一個字符數組複製函數。

C.GoBytes 把 C 語言數組複製成爲一個 Go 語言字節切片。

在 C 語言中可以通過 GoStringGoSlice 來訪問 Go 語言的字符串和切片。如果是 Go 語言中數組類型,可以將數組轉爲切片後再行轉換。如果字符串或切片對應的底層內存空間由 Go 語言的運行時管理,那麼在 C 語言中不能長時間保存 Go 內存對象。

指針類型

在 Go 語言中,指針的使用比在 C 語言中嚴格,之前我們就提到在 Go 語言中指針是不能做加減操作的,所以在 CGO 中指針的轉換就需要解決這些問題。

在 CGO 中,任何類型的指針都能強制轉換成 unsafe.Pointer 指針類型去掉原有的類型信息,然後再重新賦予新的指針類型而達到指針間的轉換的目的。例如:

var p *X
var q *Y

q = (*Y)(unsafe.Pointer(p)) // *X => *Y
p = (*X)(unsafe.Pointer(q)) // *Y => *X

參考文獻:

[1] 柴樹杉; 曹春暉, Go 語言高級編程, 北京: 人民郵電出版社, 2019.

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/aQjQ3AQwxYI5COWtNKYu5g