CGO,GOLANG調用C庫,調用代碼、靜態庫或動態庫

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

CGO

CGO可以讓golang和c互相調用,譬如x264或者aac編解碼,用go再實現一遍比較麻煩,直接調用c的函數會更合適。
CGO可以直接用C的代碼,或者C的靜態庫,或者動態庫,當然C++也是可以的。

寫了一個fdkaac的binding:https://github.com/winlinvip/go-fdkaac

參考這兩篇文章,講得很清楚:
https://golang.org/cmd/cgo/
https://blog.golang.org/c-go-cgo

有個例子,go調用x264的函數:https://github.com/winlinvip/codec

在import “C”之前加preamble(注釋),包含標頭檔。這樣在C這個命名空間中就可以用C的函數了。
這個C包,實際上是個偽包,匯入後會解析前面的preamble,用到標頭檔定義的類型、變數和函數。
preamble中可以有include,代碼,宏定義,編譯條件;靜態變數不可用,靜態函數可用。
編譯條件是用#cgo指定的,包括CFLAGS、CPPFLAGS、CXXFLAGS、LDFLAGS。
cgo指令還可以用一些變數,譬如${SRCDIR}用來連結靜態庫。

下面是個C++匯出的庫:

// winlin.h#ifdef __cplusplusextern "C"{#endif// get the version.extern int winlin_version();#ifdef __cplusplus}#endif
// winlin.cpp// g++ -c -o winlin.o winlin.cpp && ar -rs winlin.a winlin.o#include "winlin.h"int winlin_version() {    return 0x01020304;}
// main.cpp// g++ -o cpp main.cpp winlin.a#include <stdio.h>#include "winlin.h"int main(int argc, char** argv) {    printf("version is %#x\n", winlin_version());    return 0;}

下面是main.cpp在Centos6的執行結果:

[winlin@centos6 gos]$ ./cppversion is 0x1020304[winlin@centos6 gos]$ ldd cpp    linux-vdso.so.1 =>  (0x00007fff9f674000)    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003cbda00000)    libm.so.6 => /lib64/libm.so.6 (0x0000003cb0a00000)    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003cbca00000)    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)

cgo,可以在golang中用這個靜態庫:

// go run main.gopackage main// #include "winlin.h"// #cgo LDFLAGS: ${SRCDIR}/winlin.a -lstdc++import "C"import "fmt"func main() {   fmt.Println("version is", C.winlin_version())}

注意,得在h標頭檔中,使用c的方式匯出符號。

除此之外,使用c++的庫,得在LDFLAGS中加入-lstdc++。

總之,cgo的編譯和一般的c或c++差別不大,引入的庫和標頭檔之類。
運行結果如下:

[winlin@centos6 gos]$ go build -o test main.go[winlin@centos6 gos]$ ldd test    linux-vdso.so.1 =>  (0x00007fff8df9f000)    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003cbda00000)    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003cb1600000)    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)    libm.so.6 => /lib64/libm.so.6 (0x0000003cb0a00000)    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003cbca00000)[winlin@centos6 gos]$ ./testversion is 16909060

注意:preabmle可以是//,或者是//,但是不能是//,不能多個,會解析失敗。

在Centos6下面的golang程式,沒有用cgo:

[winlin@centos6 srs-plus]$ ldd objs/bocar    linux-vdso.so.1 =>  (0x00007fffb1fff000)    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003cb1600000)    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)

下面是用了cgo的golang程式:

[winlin@centos6 gos]$ ldd test    linux-vdso.so.1 =>  (0x00007ffff43ff000)    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003cb1600000)    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)

下面是C++程式:

[winlin@centos6 srs-plus]$ ldd objs/srs    linux-vdso.so.1 =>  (0x00007fff5d9ff000)    libdl.so.2 => /lib64/libdl.so.2 (0x0000003cb1200000)    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003cbda00000)    libm.so.6 => /lib64/libm.so.6 (0x0000003cb0a00000)    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003cbca00000)    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)

都只是引用了系統的so,譬如c和c++,pthread還有ldl之類的。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.