go 调用 c/c++ 函数的实现方式有:
1、直接嵌套在go文件中使用,最简单直观的;
2、导入动态库 .so 或 dll 的形式,最安全但是很不爽也比较慢的;
3、直接引用 c/c++ 文件的形式,层次分明,容易随时修改看结果的;
(1)直接嵌套在go文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package main /* // C 标志io头文件,你也可以使用里面提供的函数 #include <stdio.h>
void pri(){ printf("hey"); }
int add(int a,int b){ return a+b; } */ import "C" // 切勿换行再写这个
import "fmt"
func main() { fmt.Println(C.add(2, 1)) }
|
但凡要引用与 c/c++ 相关的内容,写到 go 文件的头部注释里面;
嵌套的 c/c++ 代码必须符合其语法,不与 go 一样;
import “C” 这句话要紧随,注释后,不要换行,否则报错;
go 代码中调用 c/c++ 的格式是: C.xxx(),例如 C.add(2, 1);
(2)导入动态库 .so 或 .dll 的形式:
假设项目目录如下

头文件 .h 如下面这样
1 2 3 4 5
| //video.h #ifndef VIDEO_H #define VIDEO_H void exeFFmpegCmd(char* cmd); // 声明 #endif
|
源文件 .c 如下面这样
1 2 3 4 5 6 7
| #include <stdio.h> #include "video.h"
void exeFFmpegCmd(char* cmd){ // 实现 // .... printf("finish"); }
|
使用 gcc 或 g++ 生成 .so库,或 win 下生成 dll
例如: gcc video.c -fPIC -shared -o libvideo.so
最后 main.go
把动态库放到一个你喜欢的目录,也可以放到当前项目里面,像上面列出的例子一样。再引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package main
/*
#cgo CFLAGS: -Iinclude
#cgo LDFLAGS: -Llib -llibvideo
#include "video.h"
*/ import "C"
import "fmt"
func main() { cmd := C.CString("ffmpeg -i ./xxx/*.png ./xxx/yyy.mp4") C.exeFFmpegCmd(&cmd) }
|
动态库会在被使用的时候被加载,影响速度
如果动态库不存在,将会爆找不到定义之类的错误信息
(3)直接引用 c/c++ 文件的形式 :
假设项目目录如下


util.go
1 2 3 4 5 6 7 8 9 10 11 12 13
| package util
/* #include "util.c" */ import "C"
import "fmt"
func GoSum(a,b int) int { s := C.sum(C.int(a),C.int(b)) fmt.Println(s) }
|
这样调用 main.go
1 2 3 4 5
| package main
func main(){ util.GoSum(4,5) }
|