爱上了Golang,C/C++ 又不想放弃。好在Go 语言提供了和C语言相互调用的机制(CGO )。包括下面几个问题
- C/C++ 调用Go 程序编写的库。
- go 语言调用C/C++ 动态和静态库。
- go 语言调用 C语言的回调程序(Callback)
- 函数之间传递参数
本文先讨论前面两个问题。
Go 和C++ 相互调用是一个十分有意义的事情,go 语言在编写网络程序,云服务等程序时,效率要比C/C++ 高许多倍。使用Go 写一个Web server 只要几行而已。而C++ 在处理底层接口时更方便一点。
C/C++ 调用 Go
首先写一个go 程序
package main
import "C"
import (
"fmt"
)
//export Foo
func Foo(a, b int) int {
return a + b;
}
//export Bar
func Bar() {
fmt.Println("Say Hello From Go")
}
func main() {}
注意: 注释 //export Foo 和 //export Bar 表示输出 两个函数
编译
go build -o golib.so -buildmode=c-shared *.go
在目录中产生了两个文件:
golib.h
golib.so
C 语言主程序
#include "golib.h"
#include <stdio.h>
int main() {
printf("%lld\n",Foo(1,2));
Bar();
return 0;
}
编译
gcc callgo.c -o callgo ./golib.so
Go 调用 C/C++
C 语言库代码(hello.c)
#include <stdio.h>
void hello(int i) {
printf("Hello C: %d\n", i);
}
hello.h
void hello(int);
Go 调用 C 动态库
编译动态库
gcc -fPIC -shared -o libhello.so hello.c
建立一个库目录mylib,将libhello.so 拷贝到 mylib 目录中。并且输出该路径路径:
export LD_LIBRARY_PATH=./mylib
go代码
package main
// #cgo CFLAGS: -I./mylib
// #cgo LDFLAGS: -L./mylib -lhello
// #include "hello.h"
import "C"
import "fmt"
func main() {
C.hello(C.int(12))
fmt.Println("Hello Go");
}
go 程序编译
go build CallC.go
Go 调用 C 静态库
首先编译和建立c 静态库
gcc -Wall -c hello.c
ar -rv libhello.a hello.o
将libhello.a 拷贝到mylib 目标中。
这里出现了问题,网络上的许多文章中都说GO 程序和动态连接是一样的,其实不然。go 程序应该为:
package main
// #cgo CFLAGS: -I./mylib
// #cgo LDFLAGS: ./mylib/libhello.a
// #include "hello.h"
import "C"
import "fmt"
func main() {
C.hello(C.int(12))
fmt.Println("Hello Go");
}
将cgo LDFLAGS 设定为静态文件名 // #cgo LDFLAGS: ./mylib/libhello.a
而编译命令是一样的
go build CallC.go