Go與C語言的操作

Go有強烈的C背景,除了語法具有繼承性外,其設計者以及其設計目標都與C語言有着千絲萬縷的聯繫。在Go與C語言互操作(Interoperability)方面,Go更是提供了強大的支持。尤其是在Go中使用C,你甚至可以直接在Go源文件中編寫C代碼,這是其他語言所無法望其項背的。下面是小編爲大家帶來的Go與C語言的操作的知識,歡迎閱讀。

Go與C語言的操作

  一、Go調用C代碼的原理

下面是一個短小的例子:

複製代碼

package main

// #include

// #include

/*

void print(char *str) {

printf("%s", str);

}

*/

import "C"

import "unsafe"

func main() {

s := "Hello Cgo"

cs := ing(s)

t(cs)

(ter(cs))

}

複製代碼

與"正常"Go代碼相比,上述代碼有幾處"特殊"的地方:

1) 在開頭的註釋中出現了C頭文件的include字樣

2) 在註釋中定義了C函數print

3) import的一個名爲C的"包"

4) 在main函數中居然調用了上述的那個C函數-print

沒錯,這就是在Go源碼中調用C代碼的步驟,可以看出我們可直接在Go源碼文件中編寫C代碼。

首先,Go源碼文件中的C代碼是需要用註釋包裹的,就像上面的include 頭文件以及print函數定義;

其次,import "C"這個語句是必須的,而且其與上面的C代碼之間不能用空行分隔,必須緊密相連。這裏的"C"不是包名,而是一種類似名字空間的概念,或可以理解爲僞包,C語言所有語法元素均在該僞包下面;

最後,訪問C語法元素時都要在其前面加上僞包前綴,比如和上面代碼中的t、等。

我們如何來編譯這個go源文件呢?其實與"正常"Go源文件沒啥區別,依舊可以直接通過go build或go run來編譯和執行。但實際編譯過程中,go調用了名爲cgo的工具,cgo會識別和讀取Go源文件中的C元素,並將其提取後交給C編譯器編譯,最後與Go源碼編譯後的目標文件鏈接成一個可執行程序。這樣我們就不難理解爲何Go源文件中的C代碼要用註釋包裹了,這些特殊的語法都是可以被Cgo識別並使用的。

  二、在Go中使用C語言的類型

1、原生類型

* 數值類型

在Go中可以用如下方式訪問C原生的數值類型:

複製代碼

,

r (signed char),

r (unsigned char),

t,

rt (unsigned short),

, (unsigned int),

,

g (unsigned long),

long (long long),

glong (unsigned long long),

t,

le

複製代碼

Go的數值類型與C中的數值類型不是一一對應的。因此在使用對方類型變量時少不了顯式轉型操作,如Go doc中的這個例子:

複製代碼

func Random() int {

return int(om())// -> Go的int

}

func Seed(i int) {

dom((i))//Go的uint -> C的uint

}

複製代碼

* 指針類型

原生數值類型的'指針類型可按Go語法在類型前面加上*,比如var p *。而void*比較特殊,用Go中的ter表示。任何類型的指針值都可以轉換爲ter類型,而ter類型值也可以轉換爲任意類型的指針值。ter還可以與uintptr這個類型做相互轉換。由於ter的指針類型無法做算術操作,轉換爲uintptr後可進行算術操作。

* 字符串類型

C語言中並不存在正規的字符串類型,在C中用帶結尾'