1. 程式人生 > >cgo通過動靜態庫呼叫c/c++

cgo通過動靜態庫呼叫c/c++

1 動靜態庫的區別

可以參考: C++靜態庫與動態庫 https://www.cnblogs.com/skynet/p/3372855.html

概括:
動靜態庫區別總結:
1 連結方式不一樣。呼叫階段不同動態庫在程式執行的時候進行呼叫,靜態庫在連結階段將彙編檔案與引用到的庫一起連結生成可執行檔案。因此前者生成的可執行檔案較後者小。 同時,當庫檔案改變時,動態庫只需要重新編譯庫檔案,而靜態庫需要編譯所有檔案。

2 庫檔案的搜尋路徑不一樣。 具體參考: ld搜尋路徑順序 https://blog.csdn.net/fightingform/article/details/47302415
或者在網站找相關資料,此處不作說明。

2編譯動靜態庫

假設有一下目錄結構及檔案

example
   - main.go
   - temp
     -  test.h
     - test.cpp
//test.h
#ifndef TEST_H  
#define TEST_H  
#ifdef __cplusplus  
extern "C"
{
#endif
int add (int a,int b);
#ifdef __cplusplus  
}
#endif
#endif
// test.cpp
#include "test.h"
int add(int a,int b)
{

return a+b;
}

現在分別進行靜動態庫編譯:

2.1靜態庫:

g++  -c  test.cpp

以上生成 test.o (-c:只編譯不連結,只生成目標檔案)

ar -scr libtest.a test.o

生成 libtest.a 靜態庫

2.2 動態庫

利用以上生成的 test.o

g++ -fPIC -shared -o libtest.so test.o

生成動態庫 libtest.so

3 cgo 使用靜態庫

// main.go
package main
/*
CPART
*/ 
import "C"
import "fmt"
func main() {
    a := C.int(3)
    b := C.int(5)
    fmt.Println(C.add(a,b))
}

以上是 main.go的程式碼,其中CPART 是下面要針對靜動態庫進行修改的。
對於靜態庫,有兩點需要注意:
1 靜態庫的尋找目錄
2 使用的靜態庫

CPART 可以改為

#cgo CFLAGS: -I ./temp
#cgo LDFLAGS: -L ./temp -ltest
#include "test.h"

執行命令

cd  example
go run main.go // or go build -o exam && ./exam

對於動態庫,依舊需要注意尋找庫的路徑,可以設定 LD_LIBRARY_PATH 環境變數,或者直接把 libtest.so 放在 /usr/lib, 然後更改 CPART 為:

#cgo CFLAGS: -I ./temp
#cgo LDFLAGS:  -ltest
#include "test.h"

程式執行與以上的方式一樣。
如果報錯:

 cannot open shared object file: No such file or directory
exit status 127

說明 沒有找到動態庫檔案, 自定義動態庫的搜尋路徑也可以看看 ldconfig 的使用

說明

1 以上的c/c++ 程式只是一個 cpp, 如果有多個的(test.cpp, test.h, exam.cpp, exam.h)該如果使用? 方法類似,可以網上找相關資料瞭解。
2 如果動態庫與靜態庫檔案放在一個目錄下,會發生什麼情況?
可以參考下:GCC 庫路徑裡同時有相同檔名的動態庫和靜態庫 https://www.cnblogs.com/mydriverc/p/7345873.html
3 gcc 與 g++ 區別
https://blog.csdn.net/na_beginning/article/details/53236968