32

C和Go相互调用

 5 years ago
source link: https://colobu.com/2018/08/28/c-and-go-calling-interaction/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

C可以调用Go,并且Go可以调用C, 如果更进一步呢, C-->Go-->C 或者 Go-->C-->Go 的调用如何实现?

本文通过两个简单的例子帮助你了解这两种复杂的调用关系。本文不涉及两者之间的复杂的数据转换,官方文章 C? Go? Cgo!wiki/cgocmd/cgo 有一些介绍。

Go-->C-->Go

Go程序调用C实现的函数,然后C实现的函数又调用Go实现的函数。

1、首先,我们新建一个 hello.go 的文件:

hello.go
package main

import "C"
import "fmt"

//export HelloFromGo
func HelloFromGo() {
 fmt.Printf("Hello from Go!\n")
}

它定义了一个 HelloFromGo 函数,注意这个函数是一个纯的Go函数,我们定义它的输出符号为 HelloFromGo

2、接着我们新建一个 hello.c 的文件:

hello.c
#include <stdio.h>
#include "_cgo_export.h"

int helloFromC() {
 printf("Hi from C\n");
 //call Go function
 HelloFromGo();
 return 0;
}

这个c文件定义了一个C函数 helloFromC ,内部它会调用我们刚才定义的 HelloFromGo 函数。

这样,我们实现了 C 调用 Go : C-->Go ,下面我们再实现Go调用C。

3、最后新建一个 main.go 文件:

main.go
package main

/*
extern int helloFromC();
*/
import "C"

func main() {
 //call c function
 C.helloFromC()
}

它调用第二步实现的C函数 helloFromC

运行测试一下:

$ go run .
Hi from C
Hello from Go!

可以看到,期望的函数调用正常的运行。第一行是C函数的输出,第二行是Go函数的输出。

C-->Go-->C

第二个例子演示了C程序调用Go实现的函数,然后Go实现的函数又调用C实现的函数。

1、首先新建一个 hello.c 文件:

hello.c
#include <stdio.h>

int helloFromC() {
 printf("Hi from C\n");
 return 0;
}

它定义了一个纯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
#include <stdio.h>
#include "hello.h"

int main() {
 printf("use hello lib from C:\n");
 
 HelloFromGo();
 
 return 0;
}

运行 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 的复杂调用。

参考文档

  1. https://medium.com/using-go-in-mobile-apps/using-go-in-mobile-apps-part-1-calling-go-functions-from-c-be1ecf7dfbc6
  2. https://github.com/vladimirvivien/go-cshared-examples
  3. http://golang.org/cmd/cgo
  4. https://gist.github.com/zchee/b9c99695463d8902cd33
  5. https://medium.com/@liamkelly17/working-with-packed-c-structs-in-cgo-224a0a3b708b

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK