Golang使用pkg-config自動獲取頭文件和鏈接庫的方法

? ?為了能夠重用已有的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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/271711.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/271711.shtml
英文地址,請注明出處:http://en.pswp.cn/news/271711.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據庫:SQLServer中with as 用法筆記

一、with as 概念介紹with as 也叫做子查詢部分&#xff08;subquery factoring&#xff09;&#xff0c;可以定義一個SQL段落&#xff0c;該SQL段落可以被整個SQL語句所用到類似于臨時表的作用。with as 可以提高你的SQL語句的可讀性&#xff0c;也有可以用在在UNION ALL的不同…

單詞

Screenshot 屏幕截圖,截圖 Dashboard n. 儀表盤 subscribe vt. 簽署&#xff1b;贊成&#xff1b;捐助 vi. 訂閱&#xff1b;捐款&#xff1b;認購&#xff1b;贊成&#xff1b;簽署 performance n. 性能&#xff1b;績效&#xff1b;表演&#xff1b;執行 optimization …

數據庫優化:SqlServer的with(nolock)關鍵字的用法介紹

一、with(nolock)的介紹數據庫寫查詢語句的時候,為了提升查詢性能,往往會在查詢的表后面加一個nolock,或者是with(nolock),其目的就是查詢的時候是不鎖定表,從而提高查詢速度的目的。但如果同一時間有多個用戶訪問同一資源的時候&#xff0c;如果并發用戶對該資源做了修改。則會…

對layoutInflater的理解

參考該博客&#xff1a;http://www.cnblogs.com/top5/archive/2012/05/04/2482328.html LayoutInflater是一個抽象類&#xff0c;通過調用其實例方法inflate()&#xff0c;將res/layout下的xml布局文件進行實例化&#xff0c;不同于findvirebyid()是找布局文件下的控件進行實例…

linux /root /etc,Linux知識:/root/.bashrc與/etc/profile的異同

要搞清bashrc與profile的區別&#xff0c;首先要弄明白什么是交互式shell和非交互式shell&#xff0c;什么是login shell 和non-login shell。交互式模式就是shell等待你的輸入&#xff0c;并且執行你提交的命令。這種模式被稱作交互式是因為shell與用戶進行交互。這種模式也是…

java多線程售票例子

代碼如下: public class Ticket1 implements Runnable {private int tickets 100;Overridepublic void run() {while (tickets > 0) {synchronized (Ticket.class) {if (tickets > 0) {tickets--;System.out.println(Thread.currentThread().getName() "正在賣票&…

推薦一款免費國產遠程辦公神器ToDesk,TeamViewer完美替代品

對于從事IT行業的人員來說&#xff0c;遠程軟件基本上是必備的軟件。之前使用用TeamViewer遠程辦公軟件&#xff0c;它的穩定性、延遲低、功能齊全很受廣大開發者的歡迎。唯一美中不足的是它是一款商業軟件。費用比較高。到現在基本上所有破解工具都無效了。所以不得不放棄這款…

[iOS] photoKit獲取所有照片

代碼: - (NSMutableArray *)getAllPhoto{NSMutableArray *arr [NSMutableArray array];// 所有智能相冊PHFetchResult *smartAlbums [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular optio…

用python寫linux中的ls,Python實現Linux環境下的ls命令

在Linux下使用ls命令結合正則表達式&#xff0c;能夠高效地進行文件搜索&#xff0c;并通過參數操作文件&#xff0c;于是就想用Python實現這個功能以便在Windows上使用import osimport reimport syspath os.getcwd()substr raw_input(The sub-string of the file (Support f…

蘋果臺式電腦怎么開機_龍華蘋果電腦回收公司,臺式電腦回收公司電話

龍華蘋果電腦回收公司,臺式電腦回收公司電話oDYIHx 通常液晶顯示器有VGA和DVI兩種種接口&#xff0c;其中VGA接口在長時間顯示后悔出現畫面模糊情況&#xff0c;需要校正才能恢復&#xff0c;然而DVi接口傳輸就比較穩定&#xff0c;它屬于全數字無損傳輸信號&#xff0c;在長…

AtomicInteger使用非阻塞算法,實現并發控制多線程實現售票

代碼如下: public class TicketDemo implements Runnable {private static volatile AtomicInteger ticketSum new AtomicInteger(20);private static int finalTotal 0;Overridepublic void run() {int count;while ((count ticketSum.decrementAndGet()) > 0) {System.…

數據庫:SQLServer 實現行轉列、列轉行用法筆記

在許多的互聯網項目當中&#xff0c;報表開發是整個項目當中很重要的一個功能模塊。其中會有一些比較復雜的報表統計需要行轉列或者列轉行的需求。今天給大家簡單介紹一下在SQLServer當中如何使用PIVOT、UNPIVOT內置函數實現數據報表的行轉列、列轉行。有需要的朋友可以一起學習…

硬件知識:串口通訊的起始、數據、停止位是怎么分配的?

串口是串行接口&#xff08;serial port&#xff09;的簡稱&#xff0c;也稱為串行通信接口或COM接口。串口通信是指采用串行通信協議&#xff08;serial communication&#xff09;在一條信號線上將數據一個比特一個比特地逐位進行傳輸的通信模式。串口按電氣標準及協議來劃分…

ES5 getter setter

最近在學習vuejs&#xff0c;了解到內部實現使用到了es5的Getters和Setters。之前看高程的時候&#xff0c;沒有重視這塊&#xff0c;今天查看一下文檔&#xff0c;了解了他們的作用&#xff0c;再次記錄一下&#xff0c;可供以后查看和共享。 定義Getters和Setters&#xff1a…

python 調用bat失敗_要想順利通過Python面試,你最起碼需要達到白銀段位!

近幾年 Python 非常熱門&#xff0c;在學術界和產業界的使用率顯著提高。目前學習Python的人數日益增多&#xff0c;Python在近3年的編程語言受歡迎度中一直處于榜首。今天我們就來講講在產業界&#xff0c;需要具備哪些能力才能獲得一個滿意的 Python 相關崗位 Offer。Python基…

多線程售票demo,用ReentrantLock實現

代碼: public class TicketReentLockDemo implements Runnable {private int ticketTotal 100;private Lock lock new ReentrantLock();Overridepublic void run() {while (ticketTotal > 0) {try {lock.lock();if (ticketTotal > 0) {try {TimeUnit.MILLISECONDS.sle…

在linux安裝不了apache,Apache 不能安裝在linux?

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓官網下載了tar.gz的文件&#xff0c; 然后tar解壓&#xff0c; 可是走到 ./configureprefix/usr/local/apache/ 的時候就開始出現一些“NO”我怕這樣make會有問題&#xff0c; 請問大家碰到出現"no"的選項嘛&#xff1f;…

andriod sqlite 詳解轉載

SQLite簡介 Google為Andriod的較大的數據處理提供了SQLite&#xff0c;他在數據存儲、管理、維護等各方面都相當出色&#xff0c;功能也非常的強大。SQLite具備下列特點&#xff1a; 1.輕量級 使用 SQLite 只需要帶一個動態庫&#xff0c;就可以享受它的全部功能&#xff0c;而…

數據庫:SQLServer中in和 exists函數用法筆記

今天給大家分享一下SQLServer中in和 exists 用法&#xff0c;希望能對大家有所幫助。一、IN 用法確定指定的值是否與子查詢或列表中的數據相匹配。1.1 語法格式test_expression [ NOT ] IN ( subquery | expression [ ,...n ] )1.2 參數說明test_expression為任意有…

什么是m叉樹_不懂數據庫索引的底層原理?那是因為你心里沒點b樹

前幾天下班回到家后正在處理一個白天沒解決的bug&#xff0c;廁所突然傳來對象的聲音&#xff1a; 對象&#xff1a;xx&#xff0c;你有《時間簡史》嗎&#xff1f; 我&#xff1a;我去&#xff01;妹子&#xff0c;你這啥癖好啊&#xff0c;我有時間也不會去撿屎啊&#xff01…