這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。cgo可以在go語言中夾雜著C函數或資料,在使用cgo時,有一些需要注意的:
1、go中的int/int32/int64/uint32/uint64和C語言中的int/int32等是不同的,因此,C語言的函數的參數不能是go語言的int,需要轉換,同理,go函數的int也不能使用C的int,需要轉換。go int轉換為C int的方法:C.int(n)還有一點,C的函數調用中,有很多參數是size_t類型,其實就是一個整型,但如果使用C.int()作為C函數的參數,就會編譯出錯: cannot use _Ctype_int(100) (type C.int) as type C.size_t in function argumentgo編譯器嚴格限制參數類型必須一致,因此必須是size_t類型的參數。這是因為go語言沒有C語言裡面的強制轉換的概念,你可以使用C.size_t(n)來得到C語言中的sizt_t類型。2、go語言中的字串和C語言中的字串轉換C.CstringC.GoString….具體可以參考文檔。3、結構體使用C.struct_xxxx如果使用struct中的成員變數,可以直接用.來訪問。4、指標使用unsafe.Pointer()來轉換,例如需要轉換為 int *:(*C.int)(unsafe.Pointer(&v))在c語言中,指標即數組,可以使用ptr[n]來獲得指標的第n個位移,但在go中,這樣不行,會報錯:invalid operation:xxxxgo語言中,指標沒有這樣的操作。需要使用unsafe.Pointer和uintptr配合來擷取指標的位移。5、函數調用C.func()文檔中說,go調用所有的C函數都會返回兩個值,後一個值為error類型,即使是void函數。文檔表述如下:n, err := C.sqrt(-1)
_, err := C.voidFunc()但我發現,C.malloc似乎只返回一個值。6、C語言中的NULL在go中是nil例如s := C.malloc(C.sizeof(100))if s == nil {….}這個很重要,在沒發現nil可以比較c的指標前,我是這樣比較的:(*C.char)(unsafe.Pointer(uintptr(0)))不過,cgo的文檔還很匱乏,很多都需要閱讀代碼。package main
/*
#include
#include
#include
struct t {
char *s;
};
*/
import “C”
import “unsafe”
import “fmt”
func main() {
var t C.struct_t
var s = “hello world”
var ch *C.char
var tmp *C.char
// 分配空間, 並判斷是否分配成功
t.s = (*C.char)(C.malloc(C.size_t(100)))
if t.s == nil {
//if t.s == (*C.char)(unsafe.Pointer(uintptr(0))) {
panic(“malloc failed!\n”)
}
// 釋放記憶體 defer C.free(unsafe.Pointer(t.s))
// 將go的字串轉為c的字串,並自動釋放
ch = C.CString(s)
defer C.free(unsafe.Pointer(ch))
// 調用C的strncpy函數複製
C.strncpy(t.s, ch, C.size_t(len(s)))
// C的指標操作
for i := C.size_t(0); i < C.strlen(t.s); i ++ {
tmp = (*C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(t.s)) + uintptr(i)))
*tmp = C.char(C.toupper(C.int(*tmp)))
}
fmt.Printf(“%s\n”, C.GoString(t.s))
fmt.Printf(“sizeof struct t is %v\n”, unsafe.Sizeof(t))
}