go語言與c語言的相互調用

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

最近由於工作原因,需要實現go語言與c語言的相互調用。由於go語言與c語言有著千絲萬縷的曖昧關係,兩者之間的調用可以通過語言層面實現。下文是對此的總結。

go語言調用c語言

以下為一個簡短的例子:

package main// #include <stdio.h>// #include <stdlib.h>/*void print(char *str) {    printf("%s\n", str);}*/import "C"import "unsafe"func main() {    s := "Hello Cgo"    cs := C.CString(s)    C.print(cs)    C.free(unsafe.pointer(cs))}

與“正常”的go代碼相比,上述代碼有幾處“特殊”的地方:

  1. 在開頭的注釋中出現了c語言標頭檔的include字樣
  2. 在注釋中定義了c語言函數print
  3. import了一個名為C的“包”
  4. 在main函數中調用了上述定義的c語言函數print

首先,go源碼檔案中的c語言代碼是需要用注釋包裹的,就像上面的include標頭檔以及print函數定義;其次,import "C"這個語句是必須的,而且其與上面的c代碼之間不能用空行分隔,必須緊密相連。這裡的”C“不是包名,而是一種類似名字空間的概念,或可以理解為偽包,c語言所有文法元素均在該偽包下面;最後,訪問c文法元素時都要在其前面加上偽包首碼,比如C.uint和上面代碼中的C.print、C.free等。

更詳細的在go中調用c語言的用法可以參考Go與C語言的互操作,本文不再一一細述。

在上面的例子中,c語言是內嵌在go代碼中的,如果代碼量更大更複雜的話,這顯然是很不”專業“的。那麼,是否可以將c語言代碼從go代碼中分離出去,單獨定義呢?答案是肯定的,可以通過共用庫的方式實現。

cgo提供了#cgo指示符可以指定go源碼在編譯後與哪些共用庫進行連結。例子如下:

// hello.gopackage main// #cgo LDFLAGS: -L ./ -lhello// #include <stdio.h>// #include <stdlib.h>// #include "hello.h"import "C"func main() {    C.hello()}// hello.c#include "hello.h"void hello(){    printf("hello, go\n");}// hello.hextern void hello();

其中在hello.go中,#cgo指示符後面添加LDFLAGS: -L ./ -lhello,作用是在go代碼編譯時間,指定在目前的目錄尋找so庫並進行連結。

因此,只需要把hello.c編譯成動態庫,再編譯go代碼,即可在運行go代碼的時候調用共用庫中的c語言函數。指令如下:

  1. gcc -fPIC -o libhello.so hello.c
  2. go build -o hello
  3. ./hello

c語言調用go語言

與在go中調用c源碼相比,在c中使用go函數的場合較少。因為一般來說,採用進階語言作為粘合劑調用低級語言能充分發揮各自的特點,而用低級語言調用進階語言反而有可能降低低級語言的效能優勢,在go中,可以使用”export + 函數名“來匯出go函數為c代碼所用,看一個簡單的例子:

// hello.gopackage mainimport "C"import "fmt"// export Go2Cfunc Go2C() {    fmt.Println("hello, C")}

可通過go build的編譯選項,將go代碼編譯成共用庫以供c代碼調用。注意,編譯so庫時必須存在main及main函數(即使main函數為空白)。編譯指令如下:go build -v -x -buildmode=c-shared -o libhello.so hello.go

編譯成功後,只需在c代碼中引入新產生的標頭檔及編譯時間連結動態庫即可實現go函數的調用。代碼如下:

// hello.c#include <stdio.h>#include "libhello.h"int main(){    Go2C();    return 0;}

通過gcc -o hello -L. -lhello,即可編譯成可執行程式。注意,運行前必須確定共用庫運行時尋找路徑中存在需要連結的共用庫,可通過將so庫路徑放到/usr/lib或者修改環境變數LD_LIBRARY_PATH。

小結

go語言可以通過內嵌c代碼的形式調用c語言,也可以通過調用共用庫函數的方式實現;至於c語言調用go函數,則可以通過go build將go代碼編譯成共用庫提供給c代碼使用。注意,本文中的共用庫均為動態共用程式庫,至於靜態共用庫則未曾實驗,有興趣的可以實現一下。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.