博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
全面总结: Golang 调用 C/C++,例子式教程
阅读量:6875 次
发布时间:2019-06-26

本文共 2281 字,大约阅读时间需要 7 分钟。

作者:林冠宏 / 指尖下的幽灵

掘金:

博客:

GitHub :

大部分人学习或者使用某样东西,喜欢在直观上看到动手后的结果,才会有继续下去的兴趣。

前言:

Golang 调用 C/C++ 的教程网上很多,就我目前所看到的,个人见解就是比较乱,坑也很多。希望本文能在一定程度上,做到更通俗明了。

下面 golang 简称 go , 一如既往,少说废话,我们现在开始。


go 调用 c/c++ 函数的实现方式有:

  • 直接嵌套在go文件中使用,最简单直观的
  • 导入动态库 .so 或 dll 的形式,最安全但是很不爽也比较慢的
  • 直接引用 c/c++ 文件的形式,层次分明,容易随时修改看结果的

第三个直接引用 c/c++ 文件的形式 是我要介绍的重点。

需要的环境支持

  • Linux 具备 gcc 与 g++ 即可
  • Windows 需要安装 ,否则编译时会有这类错:cannot find -lmingwex
  • Mac 参考 Linux

1,直接嵌套在go文件

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))}

上面的代码,直接拷贝运行就能输出结果:3

结论:

  • 但凡要引用与 c/c++ 相关的内容,写到 go 文件的头部注释里面
  • 嵌套的 c/c++ 代码必须符合其语法,不与 go 一样
  • import "C" 这句话要紧随,注释后,不要换行,否则报错
  • go 代码中调用 c/c++ 的格式是: C.xxx(),例如 C.add(2, 1)

2,导入动态库 .so 或 .dll 的形式

假设项目目录如下

|-project|  |-lib|  |  |-libvideo.dll|  |  |-libvideo.so|  |-include|  |  |-video.h|  |-src|  |  |-main.go

头文件 .h 如下面这样

//video.h#ifndef VIDEO_H#define VIDEO_Hvoid exeFFmpegCmd(char* cmd); // 声明#endif

源文件 .c 如下面这样

#include 
#include "video.h"void exeFFmpegCmd(char* cmd){ // 实现 // .... printf("finish");}

使用 gcc 或 g++ 生成 .so库,或 win 下生成 dll

例如: gcc video.c -fPIC -shared -o libvideo.so

最后 main.go

把动态库放到一个你喜欢的目录,也可以放到当前项目里面,像上面列出的例子一样。再引用

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)}

先回答为什么说这种是最安全的和最不爽的?原因如下:

  • 动态库破解十分困难,如果你的 go 代码泄露,核心动态库没那么容易被攻破
  • 动态库会在被使用的时候被加载,影响速度
  • 操作难度比方式一麻烦不少

结论

  • CFLAGS: -I路径 这句话指明头文件所在路径,-Iinclude 指明 当前项目根目录的 include 文件夹
  • LDFLAGS: -L路径 -l名字 指明动态库的所在路径,-Llib -llibvideo,指明在 lib 下面以及它的名字 video
  • 如果动态库不存在,将会爆找不到定义之类的错误信息

3,直接引用 c/c++ 文件的形式 (重点)

假设项目目录如下

|-util|  |-util.h|  |-util.c|  |-util.go

util.h

int sum(int a,int b);

util.c

#include "util.h"int sum(int a,int b){    return (a+b);}

util.go

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

package mainfunc main(){    util.GoSum(4,5)}

第三种方式便是如此简洁明了

最后,补充一下,一般需要 go 调用 c/c++ 的,主要是使用一些著名的开源库,例如 ffmpegopencv,等这些源码是基于 c/c++ 语言的,除此之外还有一个很重要的点,便是运行速度!

转载于:https://www.cnblogs.com/linguanh/p/8323487.html

你可能感兴趣的文章
VBS备份脚本
查看>>
CentOS 6.5 自动安装镜像
查看>>
Storm与Spark Streaming比较
查看>>
我的友情链接
查看>>
Exchange Server 运维管理01:Exchange中Active Directory 有什么用?
查看>>
linux系统管理之四:服务状态
查看>>
VMware View FAQ[一]
查看>>
【原创翻译】布尔值(boolean)
查看>>
三元运算式、lambda表达式、内置函数map、reduce、filter以及yield生成器
查看>>
MySQL分库分表分表后数据的查询(5th)
查看>>
iOS-点击图片放大,再次点击返回原视图 类似查看相册的功能
查看>>
JAVA -- stateless4j StateMachine 使用浅析(二)
查看>>
oracle checkpoint
查看>>
KVM虚拟化开源高可用方案(六)ISCSI ON DRBD搭建及常见故障处理
查看>>
android device related
查看>>
iOS 6 Beta3即将发布,iPhone面板谍照已经曝光
查看>>
hadoop 源码包编译
查看>>
关于scrapy的piplines
查看>>
Windows Server 2008 FTP用户目录隔离模式
查看>>
python实现linux下指定目录下文件中的单词个数统计
查看>>