Golang类似于C的静态语言,效率也接近于C,如果Golang也可以导出可供C调用的库,那可以和很多高级语言say goodbye了,goodbye似乎又有点武断,但至少说,Golang可以做很多事,而且效率优于很多高级语言,这样说应该没有问题。
接下来,就从三个方面分别来介绍Golang中关于库的使用。
Using Share Library
The latest Go @H_403_6@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的内容:
@H_403_6@ 1 package myAdd
@H_403_6@ 2
@H_403_6@ 3 func Sum(x,y int) int {
@H_403_6@ 4 return x + y
@H_403_6@ 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 @H_403_6@28
drwxr-xr-x @H_403_6@7 jack jack @H_403_6@4096 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@21 ./
drwxr-xr-x @H_403_6@11 jack jack @H_403_6@4096 @H_403_6@5月 @H_403_6@25 @H_403_6@2017 ../
drwxr-xr-x @H_403_6@2 jack jack @H_403_6@4096 @H_403_6@5月 @H_403_6@25 @H_403_6@2017 include/
drwxr-xr-x @H_403_6@30 jack jack @H_403_6@4096 @H_403_6@5月 @H_403_6@25 @H_403_6@2017 linux_386/
drwxrwxr-x @H_403_6@29 jack jack @H_403_6@4096 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 linux_386_dynlink/
drwxr-xr-x @H_403_6@3 jack jack @H_403_6@4096 @H_403_6@5月 @H_403_6@25 @H_403_6@2017 obj/
drwxr-xr-x @H_403_6@3 jack jack @H_403_6@4096 @H_403_6@5月 @H_403_6@25 @H_403_6@2017 tool/
jack@jack-VirtualBox:~/mygo/src/golib$ ll ~/go/pkg/linux_386_dynlink/
total @H_403_6@31252
drwxrwxr-x @H_403_6@29 jack jack @H_403_6@4096 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 ./
drwxr-xr-x @H_403_6@7 jack jack @H_403_6@4096 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@21 ../
drwxrwxr-x @H_403_6@2 jack jack @H_403_6@4096 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 archive/
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@121966 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@21 bufio.a
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@10 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 bufio.shlibname
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@111466 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@21 bytes.a
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@10 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 bytes.shlibname
drwxrwxr-x @H_403_6@2 jack jack @H_403_6@4096 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 compress/
drwxrwxr-x @H_403_6@2 jack jack @H_403_6@4096 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 container/
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@94220 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@21 context.a
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@10 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 context.shlibname
drwxrwxr-x @H_403_6@4 jack jack @H_403_6@4096 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 crypto/
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@20014 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@21 crypto.a
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@10 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 crypto.shlibname
drwxrwxr-x @H_403_6@3 jack jack @H_403_6@4096 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 database/
drwxrwxr-x @H_403_6@2 jack jack @H_403_6@4096 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 debug/
drwxrwxr-x @H_403_6@2 jack jack @H_403_6@4096 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 encoding/
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@5494 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@21 encoding.a
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@10 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 encoding.shlibname
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@3846 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@21 errors.a
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@10 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 errors.shlibname
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@84486 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@21 expvar.a
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@10 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@22 expvar.shlibname
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@155402 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@21 flag.a
-rw-rw-r-- @H_403_6@1 jack jack @H_403_6@10 @H_403_6@12月 @H_403_6@5 @H_403_6@09:@H_403_6@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
@H_403_6@1 package main
@H_403_6@2
@H_403_6@3 import (
@H_403_6@4 "fmt"
@H_403_6@5 "myAdd" //这就是上面自定义package,如果这里不import,只要下面用了包里面的函数,gofmt也会自动把这个包加进来,是不是有点跟使用fmt等其他包一样的用法
@H_403_6@6 )
@H_403_6@7
@H_403_6@8 func main() {
@H_403_6@9 fmt.Println("my Call application")
@H_403_6@10 fmt.Printf("Sum: %d\n",myAdd.Sum(@H_403_6@2,@H_403_6@3))
@H_403_6@11 }
jack@jack-VirtualBox:~/mygo/src$ ./main
my Call application
Sum: @H_403_6@5
Golang生成C可调用的动态库so
假设代码结构如下:
jack@jack-VirtualBox:~/mygo/src/mylib$ ls
exptest.go
jack@jack-VirtualBox:~/mygo/src/mylib$ vim exptest.go
@H_403_6@ 1 package main
@H_403_6@ 2
@H_403_6@ 3 import "C"
@H_403_6@ 4 import "fmt"
@H_403_6@ 5
@H_403_6@ 6 //export Summ
@H_403_6@ 7 func Summ(x,y int) int {
@H_403_6@ 8 return x + y
@H_403_6@ 9 }
@H_403_6@ 10
@H_403_6@ 11 //export Hello
@H_403_6@ 12 func Hello(str string) {
@H_403_6@ 13 fmt.Printf("Hello: %s\n",str)
@H_403_6@ 14 }
@H_403_6@ 15
@H_403_6@ 16 func main() {
@H_403_6@ 17 // We need the main function to make possible
@H_403_6@ 18 // CGO compiler to compile the package as C shared library
@H_403_6@ 19}
官方说法:
Go functions can be executed from C applications. They should be exported by using the following comment line: //export <your_function_name>
//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
@H_403_6@1 #include <stdio.h>
@H_403_6@2 #include "libexptest.h" //上面产生的头文件
@H_403_6@3
@H_403_6@4 int main() {
@H_403_6@5 printf("This is exptest application.\n");
@H_403_6@6 GoString str = {"Hi JXES",@H_403_6@7};
@H_403_6@7 Hello(str); //调用的函数
@H_403_6@8 printf("sum: %d\n",Summ(@H_403_6@2,@H_403_6@3)); //调用的函数
@H_403_6@9 return @H_403_6@0;
@H_403_6@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: @H_403_6@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
````
应用程序编译的方法如下:
<div class="se-preview-section-delimiter"></div>
$ gcc -o _wale _wale.c nautilus.a
“`
$ gcc -o exptest exptest.c libexptest.a
原文链接:https://www.f2er.com/go/187595.html