C和Go相互調用
C可以調用Go,并且Go可以調用C, 如果更進一步呢, C-->Go-->C 或者 Go-->C-->Go 的調用如何實現?
本文通過兩個簡單的例子幫助你了解這兩種復雜的調用關系。本文不涉及兩者之間的復雜的數據轉換,官方文章 C? Go? Cgo! 、 wiki/cgo 和 cmd/cgo 有一些介紹。
Go-->C-->Go
Go程序調用C實現的函數,然后C實現的函數又調用Go實現的函數。
1、首先,我們新建一個 hello.go 的文件:
hello.go
|
它定義了一個 HelloFromGo 函數,注意這個函數是一個純的Go函數,我們定義它的輸出符號為 HelloFromGo 。
2、接著我們新建一個 hello.c 的文件:
hello.c
|
這個c文件定義了一個C函數 helloFromC ,內部它會調用我們剛才定義的 HelloFromGo 函數。
這樣,我們實現了 C 調用 Go : C-->Go ,下面我們再實現Go調用C。
3、最后新建一個 main.go 文件:
main.go
|
它調用第二步實現的C函數 helloFromC 。
運行測試一下:
$ go run .
Hi from C
Hello from Go!
可以看到,期望的函數調用正常的運行。第一行是C函數的輸出,第二行是Go函數的輸出。
C-->Go-->C
第二個例子演示了C程序調用Go實現的函數,然后Go實現的函數又調用C實現的函數。
1、首先新建一個 hello.c 文件:
hello.c
|
它定義了一個純C實現的函數。
2、接著新建一個 hello.go 文件:
// go build -o hello.so -buildmode=c-shared .
package main
/*
extern int helloFromC();
*/
import "C"
import "fmt"
//export HelloFromGo
func HelloFromGo() {
fmt.Printf("Hello from Go!\n")
C.helloFromC()
}
func main() {
}
它實現了一個Go函數 HelloFromGo ,內部實現調用了C實現的函數 helloFromC ,這樣我們就實現了 Go-->C 。
注意包名設置為 package main ,并且增加一個空的 main 函數。
運行 go build -o hello.so -buildmode=c-shared . 生成一個C可以調用的庫,這調命令執行完后會生成 hello.so 文件和 hello.h 文件。
3、最后新建一個文件夾,隨便起個名字,比如 main
將剛才生成的 hello.so 文件和 hello.h 文件復制到 main 文件夾,并在 main 文件夾中新建一個文件 main.c :
main.c
|
運行 gcc -o main main.c hello.so 生成可執行文件 main , 運行 main :
$ ./main
use hello lib from C:
Hello from Go!
Hi from C
第一行輸出來自 main.c ,第二行來自Go函數,第三行來自 hello.c 中的C函數,這樣我們就實現了 C-->Go--C 的復雜調用。
參考文檔
- https://medium.com/using-go-in-mobile-apps/using-go-in-mobile-apps-part-1-calling-go-functions-from-c-be1ecf7dfbc6
- https://github.com/vladimirvivien/go-cshared-examples
- http://golang.org/cmd/cgo
- https://gist.github.com/zchee/b9c99695463d8902cd33
- https://medium.com/@liamkelly17/working-with-packed-c-structs-in-cgo-224a0a3b708b
來自:https://colobu.com/2018/08/28/c-and-go-calling-interaction/