作者:林冠宏 / 指尖下的幽灵
Golang 调用 C/C++ 的教程网上很多,就我目前所看到的,个人见解就是比较乱,坑也很多。希望本文能在一定程度上,做到更通俗明了。
<h2 id="go-调用-cc-函数的实现方式有">go 调用 c/c++ 函数的实现方式有:
- 直接
嵌套
在go文件中使用,最简单直观的 - 导入
动态库 .so 或 dll
的形式,最安全但是很不爽也比较慢的 - 直接引用 c/c++ 文件的形式,层次分明,容易随时修改看结果的
第三个直接引用 c/c++ 文件的形式
是我要介绍的重点。
- Linux 具备 gcc 与 g++ 即可
- Windows 需要安装 ,否则编译时会有这类错:
cannot find -lmingwex
- Mac 参考 Linux
package main
/*
// C 标志io头文件,你也可以使用里面提供的函数
#include
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))
}
cannot find -lmingwex
package main /* // C 标志io头文件,你也可以使用里面提供的函数 #includevoid pri(){
printf("hey");
}int add(int a,int b){
return a+b;
}
*/
import "C" // 切勿换行再写这个import "fmt"
func main() {
fmt.Println(C.add(2,1))
}
上面的代码,直接拷贝运行就能输出结果:3
- 但凡要引用与 c/c++ 相关的内容,写到 go 文件的头部
注释
里面
- 嵌套的 c/c++ 代码必须符合其语法,不与 go 一样
-
import "C"
这句话要紧随,注释后,不要换行,否则报错
- go 代码中调用 c/c++ 的格式是:
C.xxx()
,例如 C.add(2,1)
|-project
| |-lib
| | |-libvideo.dll
| | |-libvideo.so
| |-include
| | |-video.h
| |-src
| | |-main.go
//video.h
#ifndef VIDEO_H
#define VIDEO_H
void exeFFmpegCmd(char* cmd); // 声明
#endif
#include
#include "video.h"
void exeFFmpegCmd(char* cmd){ // 实现
// ....
printf("finish");
}
<h4 id="使用-gcc-或-g-生成-.so库或-win-下生成-dll">使用 gcc 或 g++ 生成 .so库,或 win 下生成 dll
注释
里面import "C"
这句话要紧随,注释后,不要换行,否则报错C.xxx()
,例如 C.add(2,1)
|-project
| |-lib
| | |-libvideo.dll
| | |-libvideo.so
| |-include
| | |-video.h
| |-src
| | |-main.go
//video.h
#ifndef VIDEO_H
#define VIDEO_H
void exeFFmpegCmd(char* cmd); // 声明
#endif
#include
#include "video.h"
void exeFFmpegCmd(char* cmd){ // 实现
// ....
printf("finish");
}
<h4 id="使用-gcc-或-g-生成-.so库或-win-下生成-dll">使用 gcc 或 g++ 生成 .so库,或 win 下生成 dll
//video.h #ifndef VIDEO_H #define VIDEO_H void exeFFmpegCmd(char* cmd); // 声明 #endif
#include
#include "video.h"
void exeFFmpegCmd(char* cmd){ // 实现
// ....
printf("finish");
}
<h4 id="使用-gcc-或-g-生成-.so库或-win-下生成-dll">使用 gcc 或 g++ 生成 .so库,或 win 下生成 dll
void exeFFmpegCmd(char* cmd){ // 实现
// ....
printf("finish");
}
例如: gcc video.c -fPIC -shared -o libvideo.so
把动态库放到一个你喜欢的目录,也可以放到当前项目里面,像上面列出的例子一样。再引用
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)
}
<h4 id="先回答为什么说这种是最安全的和最不爽的原因如下">先回答为什么说这种是最安全的和最不爽的?原因如下:
- 动态库破解十分困难,如果你的 go 代码泄露,核心动态库没那么容易被攻破
- 动态库会在被使用的时候被加载,影响速度
- 操作难度比方式一麻烦不少
-
CFLAGS: -I路径
这句话指明头文件所在路径,-Iinclude 指明 当前项目根目录的 include 文件夹
-
LDFLAGS: -L路径 -l名字
指明动态库的所在路径,-Llib -llibvideo,指明在 lib 下面以及它的名字 video
- 如果动态库不存在,将会爆
找不到定义之类
的错误信息
(重点)
|-util
| |-util.h
| |-util.c
| |-util.go
int sum(int a,int b);
#include "util.h"
int sum(int a,int b){
return (a+b);
}
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)
}
<h4 id="这样调用-main.go">这样调用 main.go
<pre class="golang">package main
func main(){
util.GoSum(4,5)
}
CFLAGS: -I路径
这句话指明头文件所在路径,-Iinclude 指明 当前项目根目录的 include 文件夹LDFLAGS: -L路径 -l名字
指明动态库的所在路径,-Llib -llibvideo,指明在 lib 下面以及它的名字 video找不到定义之类
的错误信息|-util | |-util.h | |-util.c | |-util.go
int sum(int a,int b);
#include "util.h"
int sum(int a,int b){
return (a+b);
}
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)
}
<h4 id="这样调用-main.go">这样调用 main.go
<pre class="golang">package main
func main(){
util.GoSum(4,5)
}
#include "util.h" int sum(int a,int b){ return (a+b); }
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)
}
<h4 id="这样调用-main.go">这样调用 main.go
/*
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)
}
<pre class="golang">
package main
func main(){
util.GoSum(4,5)
}
第三种方式便是如此简洁明了
。
最后,补充一下,一般需要 go 调用 c/c++ 的,主要是使用一些著名的开源库,例如 ffmpeg
,opencv
,等这些源码是基于 c/c++ 语言的,除此之外还有一个很重要的点,便是运行速度!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。