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

掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8

博客:http://www.cnblogs.com/linguanh/

GitHub : https://github.com/af913337456/

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

前言:

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

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


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

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

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

需要的环境支持

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

1,直接嵌套在go文件

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

上面的代码,直接拷贝运行就能输出结果: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_H
void exeFFmpegCmd(char* cmd); // 声明
#endif

源文件 .c 如下面这样

#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

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


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 main

func main(){
util.GoSum(4,5)
}

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

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

全面总结: Golang 调用 C/C++,例子式教程的更多相关文章

  1. Golang 调用 C/C++,例子式教程

    大部分人学习或者使用某样东西,喜欢在直观上看到动手后的结果,才会有继续下去的兴趣. 前言: Golang 调用 C/C++ 的教程网上很多,就我目前所看到的,个人见解就是比较乱,坑也很多.希望本文能在 ...

  2. golang调用c++的dll库文件

    最近使用golang调用c++的dll库文件,简单了解了一下,特作此笔记:一.DLL 的编制与具体的编程语言及编译器无关 dll分com的dll和动态dll,Com组件dll:不管是何种语言写的都可以 ...

  3. Golang调用windows下的dll动态库中的函数

    Golang调用windows下的dll动态库中的函数 使用syscall调用. package main import ( "fmt" "syscall" & ...

  4. golang生成c-shared so供c语言或者golang调用到例子

    1.golang生成c-shared类型到so 建立文件夹hello,创建main.go文件,内容如下 package main import "C" func main() {} ...

  5. LevelDB性能测试|Golang调用LevelDB

    LevelDB性能测试|Golang调用LevelDB 不同方式使用压力测试 用ssdb,TCP连接方式调用,底层存储levelDB 直接调用Cgo的levelDB (必须保证串行) 直接调用Gola ...

  6. Golang调用Python

    https://yq.aliyun.com/articles/117329 Python是时髦的机器学习御用开发语言,Golang是大红大紫的新时代后端开发语言.Python很适合让搞算法的写写模型, ...

  7. golang调用c动态库

    golang调用c动态库 简介 golang调用c语言动态库,动态方式调用,可指定动态库路径,无需系统目录下 核心技术点 封装c动态库 go语言调用c代码 实例代码 封装c动态库 头文件 test_s ...

  8. Golang 调用 aws-sdk 操作 S3对象存储

    Golang 调用 aws-sdk 操作 S3对象存储 前言 因为业务问题,要写一个S3对象存储管理代码,由于一直写Go,所以这次采用了Go,Go嘛,快,自带多线程,这种好处就不用多说了吧. 基础的功 ...

  9. Golang调用Dll案例

    Golang调用Dll案例 前言 在家办公已经两个多星期了,目前最大的困难就是网络很差.独自一个人用golang开发调用dll的驱动程序.本来就是半桶水的我,还在为等待打开一个页面而磨平了耐心.本想依 ...

随机推荐

  1. idea和Webstorm上使用git和github,码云

    由于之前一直使用svn,现在项目使用git,顾根据网上找的学习资料,自己梳理了下,收获蛮多,这里做个记录,如果能帮助到您那是最好不过的. 1.大致步骤 使用工具:idea,github,码云 webs ...

  2. 配置nginx支持path_info模式

    简介:我们用thinkphp,CodeIgniter框架的时候,地址基本都是IP/index.php/group_controller?***的模式,通过index.php入口访问php文件 这种模式 ...

  3. web.xml文件--编码注意事项

    写在前面: 最近发布项目的时候,要修改web.xml文件的内容,然后我在本机的web.xml文件中是有注释的,但是到了服务器上面,就说编码不同.我也没有怎么注意.就继续启动服务器,但是访问网站,一直报 ...

  4. 【java】实现一个简单的正则:判断一个字符串是否全由数字组成

    package 正则; public class TestIsNum { public static void main(String[] args) { String s1="abc&qu ...

  5. iOS ShareSDK 三方分享/登录使用

    原文 http://www.cnblogs.com/CoderAlex/p/4860352.html 一: 快速集成 1.前言 作为现在App里必不可少的用户分享需要,社交化分享显然是我们开发app里 ...

  6. 视觉SLAM的数学表达

    相机是在某些时刻采集数据的,所以只关心这些时刻的位置和地图. 就把这一段时间的运动变成了李三时刻 t=1,2,...K当中发生的事情. 在这些事可,x表示机器自身的位置. x1,x2,x3,x4... ...

  7. 滚动条大于120px时,判断pc端的情况下,导航条固定定位

      //滚动条大于120px时,判断pc端的情况下,导航条固定定位 $(window).scroll(function(){ var viewWidth=$(document).width() var ...

  8. 【转】java jvm 线程 与操作系统线程

    原文链接:http://segmentfault.com/q/1010000000370403 Java的目标是要跨平台,而不同的操作系统(如类Unix和Windows)其任务调度机制有很大的不同,故 ...

  9. bootstrap 导航栏鼠标悬停显示下拉菜单

    在jsp中加入一下代码: .navbar .nav > li:hover .dropdown-menu { display: block;} 全部代码如下所示: <%@ page lang ...

  10. c# 调用python语言

    config   文件配置 <configuration>节中 第一个的位置插入如下节点,版本根据实际用到的来写 <configSections>    <section ...