日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

go语言调用c 的头文件 so,Golang生成共享库(shared library)以及Golang生成C可调用的动态库.so和静态库.a...

發布時間:2023/11/30 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 go语言调用c 的头文件 so,Golang生成共享库(shared library)以及Golang生成C可调用的动态库.so和静态库.a... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Golang類似于C的靜態語言,效率也接近于C,如果Golang也可以導出可供C調用的庫,那可以和很多高級語言say goodbye了,goodbye似乎又有點武斷,但至少說,Golang可以做很多事,而且效率優于很多高級語言,這樣說應該沒有問題。

接下來,就從三個方面分別來介紹Golang中關于庫的使用。

Using Share Library

The latest Go 1.5 version is out. As part of the new features, Go compiler can compile packages as a shared libraries.

It accepts -buildmode argument that determines how a package is compiled. These are the following options:

* archive: Build the listed non-main packages into .a files. Packages named main are ignored.

* c-archive: Build the listed main package, plus all packages it imports, into a C archive file.

* c-shared: Build the listed main packages, plus all packages that they import, into C shared libraries.

* shared: Combine all the listed non-main packages into a single shared library.

* exe: Build the listed main packages and everything they import into executables. Packages not named main are ignored.

By default, listed main packages are built into executables and listed non-main packages are built into .a files.

平時編譯、運行golang,可能用得比較多的是下面這些:

go run xxx.go //直接運行xxx.go,有點類似解釋語言,比如lua, python,其實執行go run,是對源文件做了build,然后再run執行文件的,只是這些都在后臺做了

go build xxx.go //編譯產生同名的執行檔,如果在源文件目錄下直接go build會產生與目錄名同名的可執行檔

go install xxx.go //也是編譯,只是編譯后會將同名的執行檔安裝到$GOPATH/bin下面,同樣在源文件目錄下直接go install,會把與目錄同名的可執行檔安裝在$GOPATH/bin下

以上的go build都是默認的編譯,也就是-buildmode是default的

By default, listed main packages are built into executables and listed non-main packages are built into .a files.

現在進入正題,這里我主要是要說明下面這個選項的使用方法:

* shared: Combine all the listed non-main packages into a single shared library.

我們先看一個hello world的例子:

package main

import "fmt"

int main(){

fmt.Println("hello world")

}

這里的fmt就是一個share library,這是go里面自帶的,現在如果想自定義一個共享庫,應該怎么做?

假設在$GOPATH/src下有:

--myAdd --add.go--myCall --main.go

詳細目錄如下:

jack@jack-VirtualBox:~/mygo/src$echo $GOPATH

/home/jack/mygo

jack@jack-VirtualBox:~/mygo$ls

bin pkg src

jack@jack-VirtualBox:~/mygo/src$ls myAdd

add.go

jack@jack-VirtualBox:~/mygo/src$ls myCall

main.go

現在我們要自定義一個myAdd的package,像fmt一樣的使用,先看下myAdd/add.go的內容:

1 package myAdd

2

3 func Sum(x, y int) int {

4 return x + y

5 }

在編譯自定義package前,先看下官方怎么說:

Before compile any shared library, the standard builtin packages should be installed as shared library. This will allow any other shared library to link with them.

意思是在編譯任何共享包前,先要把官方自身的標準包先以共享包方式安裝下,這樣其他的包就可以與它們做link。

下面就按官方要求先來編譯一下:

jack@jack-VirtualBox:~/mygo/src/myAdd$go install -buildmode=shared -linkshared std

編譯后會在GOROOT的pkg目錄下安裝標準共享庫, 這里對應linux_386_dynlink這個目錄:

jack@jack-VirtualBox:~/mygo/src/golib$ ll ~/go/pkg

total 28

drwxr-xr-x 7 jack jack 4096 12月 5 09:21 ./

drwxr-xr-x 11 jack jack 4096 5月 25 2017 ../

drwxr-xr-x 2 jack jack 4096 5月 25 2017 include/

drwxr-xr-x 30 jack jack 4096 5月 25 2017 linux_386/

drwxrwxr-x 29 jack jack 4096 12月 5 09:22 linux_386_dynlink/

drwxr-xr-x 3 jack jack 4096 5月 25 2017 obj/

drwxr-xr-x 3 jack jack 4096 5月 25 2017 tool/

jack@jack-VirtualBox:~/mygo/src/golib$ ll ~/go/pkg/linux_386_dynlink/

total 31252

drwxrwxr-x 29 jack jack 4096 12月 5 09:22 ./

drwxr-xr-x 7 jack jack 4096 12月 5 09:21 ../

drwxrwxr-x 2 jack jack 4096 12月 5 09:22 archive/

-rw-rw-r-- 1 jack jack 121966 12月 5 09:21 bufio.a

-rw-rw-r-- 1 jack jack 10 12月 5 09:22 bufio.shlibname

-rw-rw-r-- 1 jack jack 111466 12月 5 09:21 bytes.a

-rw-rw-r-- 1 jack jack 10 12月 5 09:22 bytes.shlibname

drwxrwxr-x 2 jack jack 4096 12月 5 09:22 compress/

drwxrwxr-x 2 jack jack 4096 12月 5 09:22 container/

-rw-rw-r-- 1 jack jack 94220 12月 5 09:21 context.a

-rw-rw-r-- 1 jack jack 10 12月 5 09:22 context.shlibname

drwxrwxr-x 4 jack jack 4096 12月 5 09:22 crypto/

-rw-rw-r-- 1 jack jack 20014 12月 5 09:21 crypto.a

-rw-rw-r-- 1 jack jack 10 12月 5 09:22 crypto.shlibname

drwxrwxr-x 3 jack jack 4096 12月 5 09:22 database/

drwxrwxr-x 2 jack jack 4096 12月 5 09:22 debug/

drwxrwxr-x 2 jack jack 4096 12月 5 09:22 encoding/

-rw-rw-r-- 1 jack jack 5494 12月 5 09:21 encoding.a

-rw-rw-r-- 1 jack jack 10 12月 5 09:22 encoding.shlibname

-rw-rw-r-- 1 jack jack 3846 12月 5 09:21 errors.a

-rw-rw-r-- 1 jack jack 10 12月 5 09:22 errors.shlibname

-rw-rw-r-- 1 jack jack 84486 12月 5 09:21 expvar.a

-rw-rw-r-- 1 jack jack 10 12月 5 09:22 expvar.shlibname

-rw-rw-r-- 1 jack jack 155402 12月 5 09:21 flag.a

-rw-rw-r-- 1 jack jack 10 12月 5 09:22 flag.shlibname

//GOROOT如下:

jack@jack-VirtualBox:~/samba_share/golang$echo $GOROOT

/home/jack/go

接下來,就可以編譯自定義的共享庫,并link到標準std庫:

jack@jack-VirtualBox:~/mygo/src$go install -buildmode=shared -linkshared myAdd

jack@jack-VirtualBox:~/mygo/src$ls

github.com golang.org myAdd test

jack@jack-VirtualBox:~/mygo/src$ls myAdd/

add.go //這里并沒有產生仍何文檔,產生在那里接著向下看

實際產生共享是在GOPATH/pkg目錄下:

jack@jack-VirtualBox:~/mygo$ls

bin pkg src

jack@jack-VirtualBox:~/mygo$ls pkg

linux_386 linux_386_dynlink

jack@jack-VirtualBox:~/mygo$ls pkg/linux_386_dynlink/

libmyAdd.so myAdd.a myAdd.shlibname //這些庫在編譯時已經鏈接到標準std庫,所以下面在應用程序中可以直接使用。

下面是應用程序的代碼:

jack@jack-VirtualBox:~/mygo/src$ vim myCall/main.go

1 package main

2

3 import (

4 "fmt"

5 "myAdd" //這就是上面自定義package,如果這里不import,只要下面用了包里面的函數,gofmt也會自動把這個包加進來,是不是有點跟使用fmt等其他包一樣的用法

6 )

7

8 func main() {

9 fmt.Println("my Call application")

10 fmt.Printf("Sum: %d\n", myAdd.Sum(2, 3))

11 }

jack@jack-VirtualBox:~/mygo/src$ ./main

my Call application

Sum: 5

Golang生成C可調用的動態庫so

假設代碼結構如下:

jack@jack-VirtualBox:~/mygo/src/mylib$ ls

exptest.go

jack@jack-VirtualBox:~/mygo/src/mylib$ vim exptest.go

1 package main

2

3 import "C"

4 import "fmt"

5

6 //export Summ

7 func Summ(x, y int) int {

8 return x + y

9 }

10

11 //export Hello

12 func Hello(str string) {

13 fmt.Printf("Hello: %s\n", str)

14 }

15

16 func main() {

17 // We need the main function to make possible

18 // CGO compiler to compile the package as C shared library

19}

官方說法:

Go functions can be executed from C applications. They should be exported by using the following comment line://export

//export your_function_name目的是產生對應的頭文件函數聲明,以及cgo的與C之間一些轉換規則,詳細可以參考生成的頭文件。

另外,import “C”這個也是不能少的,表示導入一個C庫

下面就是編譯共享庫:

//The packaged should be compiled with buildmode flags c-shared or c-archive:

jack@jack-VirtualBox:~/mygo/src/mylib$ go build -buildmode=c-shared -o libexptest.so exptest.go

jack@jack-VirtualBox:~/mygo/src/mylib$ ls

exptest.go libexptest.h libexptest.so

下面寫一個C程序調用這個so動態庫:

jack@jack-VirtualBox:~/mygo/src/mylib$vim exptest.c

1 #include

2 #include "libexptest.h" //上面產生的頭文件

3

4 int main() {

5 printf("This is exptest application.\n");

6 GoString str = {"Hi JXES", 7};

7 Hello(str); //調用的函數

8 printf("sum: %d\n", Summ(2, 3)); //調用的函數

9 return 0;

10 }

jack@jack-VirtualBox:~/mygo/src/mylib$export LD_LIBRARY_PATH=./

jack@jack-VirtualBox:~/mygo/src/mylib$echo $LD_LIBRARY_PATH

./

jack@jack-VirtualBox:~/mygo/src/mylib$./exptest

This is exptest application.

Hello: Hi JXES

sum: 5

這里需要說明下,在linux系統中應用程序關聯到共享庫時,都是從LD_LIBRARY_PATH環境變量指定的目錄下找需要的.so,所以這里一定要指定在當前目錄,如果不指定,可以把產生的so文件復制到/usr/lib下也可以。

Golang調用靜態庫.a

產生靜態庫只是編譯的時候產生.a的靜態庫,庫與測試程序代碼如上,編譯方法是:

jack@jack-VirtualBox:~/mygo/src/mylib$ go build -buildmode=c-archive -o libexptest.so exptest.go

jack@jack-VirtualBox:~/mygo/src/mylib$ ls

exptest.go libexptest.h libexptest.a

````

應用程序編譯的方法如下:

$ gcc -o exptest exptest.c libexptest.a “`

總結

以上是生活随笔為你收集整理的go语言调用c 的头文件 so,Golang生成共享库(shared library)以及Golang生成C可调用的动态库.so和静态库.a...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。