Récemment, pour des raisons professionnelles, il est nécessaire de mettre en œuvre des appels mutuels entre le langage go et le langage c. Le langage Go et le langage C étant inextricablement liés, les appels entre les deux peuvent se réaliser à travers le niveau du langage. Vous en trouverez ci-dessous un résumé.
le langage go appelle le langage c
Ce qui suit est un court exemple :
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)) }
Par rapport au code go "normal", le code ci-dessus a plusieurs choses "spéciales" :
apparaît dans les commentaires au début L'inclusion word dans le fichier d'en-tête du langage c
définit la fonction du langage c print dans le commentaire
importe un "package" nommé C
appelle le langage c défini ci-dessus dans la fonction principale Function print
Tout d'abord, le code du langage C dans le fichier source go doit être enveloppé de commentaires, tout comme le fichier d'en-tête d'inclusion et la définition de la fonction d'impression ci-dessus. Deuxièmement, l'instruction d'importation "C" est nécessaire et elle est liée à The ; Les codes C ci-dessus ne peuvent pas être séparés par des lignes vides et doivent être étroitement liés. Le "C" ici n'est pas un nom de package, mais un concept similaire à un espace de noms, ou il peut être compris comme un pseudo-paquet. Tous les éléments de syntaxe du langage C se trouvent finalement sous ce pseudo-paquet, lors de l'accès à la syntaxe C ; éléments, ils doivent être devant lui. Ajoutez des préfixes de pseudo-package, tels que C.uint et C.print, C.free, etc. dans le code ci-dessus.
Pour une utilisation plus détaillée de l'appel du langage C dans Go, veuillez vous référer à l'interopérabilité entre Go et le langage C. Cet article n'entrera pas dans les détails un par un.
Dans l'exemple ci-dessus, le langage C est intégré dans le code go. Si le code est plus volumineux et plus complexe, ce n'est évidemment pas du tout professionnel. Alors, le code du langage C peut-il être séparé du code Go et défini séparément ? La réponse est oui, cela peut être réalisé grâce à des bibliothèques partagées.
cgo fournit la directive #cgo
pour spécifier à quelles bibliothèques partagées le code source go sera lié après la compilation. L'exemple est le suivant : #cgo
指示符可以指定go源码在编译后与哪些共享库进行链接。例子如下:
// hello.go package 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.h extern void hello();
其中在hello.go中,#cgo
指示符后面添加LDFLAGS: -L ./ -lhello
,作用是在go代码编译时,指定在当前目录查找so库并进行链接。
因此,只需要把hello.c编译成动态库,再编译go代码,即可在运行go代码的时候调用共享库中的c语言函数。指令如下:
gcc -fPIC -o libhello.so hello.c
go build -o hello
./hello
c语言调用go语言
与在go中调用c源码相比,在c中使用go函数的场合较少。因为一般来说,采用高级语言作为粘合剂调用低级语言能充分发挥各自的特点,而用低级语言调用高级语言反而有可能降低低级语言的性能优势,在go中,可以使用”export + 函数名“来导出go函数为c代码所用,看一个简单的例子:
// hello.go package main import "C" import "fmt" // export Go2C func 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
rrreee
LDFLAGS: -L ./ -lhello
après l'indicateur #cgo
, qui est utilisé lors de la compilation du code go . Spécifie qu'il faut rechercher la bibliothèque so dans le répertoire actuel et la lier.