为了能够重用已有的C语言库,我们在使用Golang开发项目或系统的时候难免会遇到Go和C语言混合编程,这时很多人都会选择使用cgo。 话说cgo这个东西可算得上是让人又爱又恨,好处在于它可以让你快速重用已有的C语言库,无需再用Golang重造一遍轮子,而坏处就在于它会在一定程度 上削弱你的系统性能。关于cgo的种种劣迹,Dave Cheney大神在他的博客上有一篇专门的文章《cgo is not Go》,感兴趣的同学可以看一看。但话说回来,有时候为了快速开发满足项目需求,使用cgo也实在是不得已而为之。

 
       在Golang中使用cgo调用C库的时候,如果需要引用很多不同的第三方库,那么使用#cgo CFLAGS:和#cgo LDFLAGS:的方式会引入很多行代码。首先这会导致代码很丑陋,最重要的是如果引用的不是标准库,头文件路径和库文件路径写死的话就会很麻烦。一旦第 三方库的安装路径变化了,Golang的代码也要跟着变化,所以使用pkg-config无疑是一种更为优雅的方法,不管库的安装路径有何变化,我们都不 需要修改Go代码,接下来本博主就用一个简单的例子来说明如何在cgo命令中使用pkg-config。
 
       首先假定我们在路径/home/ubuntu/third-parties/hello下安装了一个名称为hello的第三方C语言库,其目录结构如下所示,在hello_world.h中只定义了一个接口函数hello,该函数接收一个char *字符串作为变量并调用printf将其打印到标准输出。
 
# tree /home/ubuntu/third-parties/hello/
/home/ubuntu/third-parties/hello/
├── include
│   └── hello_world.h
└── lib
    ├── libhello.so
    └── pkgconfig
        └── hello.pc

 
       为了保证pkg-config能够找到这个C语言库,我们要为这个库生成一个描述文件,也就是lib/pkgconfig目录下的hello.pc,其内容如下,有不了解该配置文件内容的看客们可以去搜索一下pkg-config的相关文档。
 
# cat hello.pc 
prefix=/home/ubuntu/third-parties/hello
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${exec_prefix}/include
Name: hello
Description: The hello library just for testing pkgconfig
Version: 0.1
Libs: -lhello -L${libdir}
Cflags: -I${includedir}

 
       完成pkg-config描述文件的创建后,还需要将该描述文件的路径信息添加到PKG_CONFIG_PATH环境变量中,只有这样 pkg-config才能正确获取这个C语言库的相关信息。此外,我们还需要将该C语言库的库文件路径添加到LD_LIBRARY_PATH环境变量中, 具体命令如下:
 
# export PKG_CONFIG_PATH=/home/ubuntu/third-parties/hello/lib/pkgconfig
# pkg-config --list-all | grep libhello
libhello    libhello - The hello library just for testing pkgconfig
# export LD_LIBRARY_PATH=/home/ubuntu/third-parties/hello/lib

 
       在完成以上一系列准备工作之后,我们就可以开始编写Golang代码了,以下是Golang调用C语言接口的代码示例,我们只需要#cgo pkg-config: libhello和#include < hello_world.h >两行语句即可实现对hello函数的调用。如果C语言库的安装路径发生了变化,只需修改hello.pc这个描述文件即可,Golang代码无需重新修改和编译。
 
package main
// #cgo pkg-config: libhello
// #include < stdlib.h >
// #include < hello_world.h >
import "C"
import (
"unsafe"
)
func main() {
msg := "Hello, world!"
cmsg := C.CString(msg)
C.hello(cmsg)
C.free(unsafe.Pointer(cmsg))
}

 
       最后,编译该程序代码,查看可执行程序是否正确链接了C语言库,执行程序验证能否正确调用库函数功能。
 
# go build hello_world.go 
# ldd hello_world
linux-vdso.so.1 =>  (0x00007ffff63d3000)
libhello.so => /home/ubuntu/third-parties/hello/lib/libhello.so (0x00007fc31c0e1000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc31bec3000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc31bafe000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fc31c2e3000)
# ./hello_world 
Hello, world!

 
       在以上步骤中需要关注的有两个地方:1)创建C语言库的pkg-config配置文件并将配置文件的路径添加到环境变量 PKG_CONFIG_PATH中;2)C语言库文件的路径添加到环境变量LD_LIBRARY_PATH中,如果没有这一步,Go语言程序可以编译成 功,但是可执行文件无法正确连接到C语言库,会出现如下情况:
 
# ldd hello_world
linux-vdso.so.1 =>  (0x00007fffa49e2000)
libhello.so => not found
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007feb0fe93000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007feb0face000)
        /lib64/ld-linux-x86-64.so.2 (0x00007feb100b1000)

转载于:https://www.cnblogs.com/satng/p/5538926.html

Golang使用pkg-config自动获取头文件和链接库的方法相关推荐

  1. VS_自动添加头文件

    2019独角兽企业重金招聘Python工程师标准>>> 有时候,我们因为层级太乱,还手动添加可能出错,不愿意手动去写#include<>来加入头文件,就可以用自动添加头文 ...

  2. ios逆向- 01逆向原理Class-dump安装及获取头文件

    逆向原理 动态调试 通过界面调试Cycript\Xcode LLDB! 静态分析 利用之前学习的汇编代码,分析三方APP的源码! 代码注入 注入的其实是动态库!HOOK代码 改变原来程序的执行流程! ...

  3. linux 头文件卫士,条件编译,头文件,静态库,共享库与多文件编程

    原标题:条件编译,头文件,静态库,共享库与多文件编程 本文转载自嵌入式Linux中文站条件编译 条件编译即满足某些条件的时候编译某部分代码,常用于开发多个版本的程序,当满足条件A时,编译出免费版本的软 ...

  4. 【Android RTMP】音频数据采集编码 ( FAAC 头文件与静态库拷贝到 AS | CMakeList.txt 配置 FAAC | AudioRecord 音频采样 PCM 格式 )

    文章目录 安卓直播推流专栏博客总结 一. FAAC 头文件与静态库拷贝到 Android Studio 二. CMakeList.txt 构建脚本配置 三. Java 层 AudioRecord 音频 ...

  5. 【Android FFMPEG 开发】Android Studio 工程配置 FFMPEG ( 动态库打包 | 头文件与函数库拷贝 | CMake 脚本配置 )

    文章目录 I . FFMPEG 交叉编译后的函数库及头文件 II . FFMPEG 静态库打包动态库 ( 仅做参考 ) III . 创建 Android Studio 工程 IV . FFMPEG 头 ...

  6. conan入门(二十):封装只包含头文件(header_only)的库示例

    conan: 封装只包含头文件(header_only)的库示例 有的C/C++项目只包含头文件,不需要编译,对于这种情况如何封装为Conan的包呢? Conan官方文档 <Package sc ...

  7. c语言的函数头书写标准,C语言的头文件的函数和书写方法.doc

    C语言的头文件的函数和书写方法 C语言头文件作用及写法 头文件几个好处: 1,头文件可以定义所用的函数列表,方便查阅你可以调用的函数:2,头文件可以定义很多宏定义,就是一些全局静态变量的定义,在这样的 ...

  8. c++中algorithm头文件、STL库简介及使用说明

    c++中algorithm头文件.STL库简介及使用说明 c++中algorithm头文件是STL的算法部分,里边定义了各种算法,比如sort之类的.加上algorithm就可以使用stl库里的各种算 ...

  9. java 获取包路径_java获取java文件路径的四种方法

    java获取java文件路径的四种方法 发布时间:2020-04-17 11:03:45 来源:亿速云 阅读:750 作者:小新 今天小编给大家分享的是java获取java文件路径的四种方法,很多人都 ...

最新文章

  1. python实现流媒体传输_基于OpenCV的网络实时视频流传输的实现
  2. MySQL的索引及优化方案
  3. python用turtle库绘制树图形_使用Python中的Turtle库绘制简单的图形
  4. 北斗导航 | GPS原理与接收机设计——青冥剑(金码、C/A码、P码)
  5. Linux 中 Iptables 规则定义
  6. 计算机二级-C语言-对标志位的巧妙使用。对二维数组数据进行处理。对文件进行数据输入。...
  7. XPath总结(转)
  8. “不能初始化photoshop,因为暂存盘已满”图文解决方案
  9. OpenCV零基础从配置环境到读取图片,输出各种灰度腐蚀图,最后输出直方图,做矩阵运算等等
  10. 在LINUX环境下怎样设置无线网络配置
  11. 人脸识别撞脸名画_人脸识别_“名画匹配”刷爆屏 想知道你和哪副名画撞脸了吗...
  12. php实现addon安装卸载,插件Addon文件
  13. C语言|博客作业06
  14. 利用短时傅里叶变换(STFT)对信号进行时频谱分析和去噪声
  15. 统计英文文件中单词出现频率
  16. 100道iOS面试题
  17. 2021-10-18血压计方案|血压计模块
  18. 教你使用 koa2 + vite + ts + vue3 + pinia 构建前端 SSR 企业级项目
  19. docker连接wind10本地pycharm pro
  20. 米筐量化如何安装使用?

热门文章

  1. vue使用webPack打包发布后页面显示空白
  2. jquery --- 网页选项卡
  3. vue --- vue.js实战基础篇课后练习
  4. 小程序跨行跨列多列复杂表格实现
  5. Maven中使用本地JAR包
  6. Android得到一个闹钟在第三方
  7. PHP的session阻塞问题
  8. ceres-solver学习笔记
  9. 低功耗设计——功耗估算
  10. 逻辑综合——施加约束