0%

c 调用 go

当学习一门新语言时我们可能希望把我们会的东西带到新语言上面,例如我自己。我在学习新语言时,一些目前搞不定的事我可能会用我会的语言先进行解决然后将处理结果通过 http 返回 新语言进行处理,而 通过 c 语言进行调用时另外一种方式,因为现代语言一般都会预留 c 语言的接口。

什么你问我 为什么不在 go 里调用 c 因为不是万不得已。我更希望纯go

本次演示在 debian10 下进行因为需要用到 gcc 而 cgo 的 c 部分用 linux 最容易解决如果你是用的 其它操作系统请切换到 linux 进行

接下来我们就开始编写代码了

首先创建一个项目,别问我怎么创建因为 c 调用 go 并不是经常需要,你能有这样的需求,那么应该不是新手了。

在项目内创建 foobar.go 写入以下内容

// foobar.go
package main

import "C" // 伪包由 cgo 进行处理

import (
    "fmt"
)

// Foobar 这里的 godoc 注释并不影响导出
//export Foobar
func Foobar() { // 必须要 export 否则不会构建生成 C 所需的头文件
    fmt.Println("foobar")
}

func main() {} // 必须要有main函数才会被编译

上面的代码写好后就开始生成动态连了

生成动态链

go build -o foobar.so -buildmode=c-shared foobar.go

这回在你的项目下生成 两个文件 foobar.so 以及 foobar.h
foobar.go 是动态链在编译时需要到 foobar.h 是头文件在编写代码时需要用到

创建一个名为 main.c 的文件并写入以下内容

// main.c
#include "foobar.h"

void main() { // 你以为我要 int mian 我就不
    Foobar(); // 调用导出的 go 函数
}

接下来就可以生成可执行文件

gcc main.c -o main ./foobar.so

运行程序

./main

不出意外的话应该会输出

foobar

参考

https://blog.golang.org/cgo
https://golang.org/cmd/cgo/
https://github.com/golang/go/wiki/cgo