cgo 調用練習, 簡單愚蠢命令列詞典

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

在go 的程式中調用 c 代碼, golang 提供了兩種方法:   cgo, swing 。gstreamer 是開源跨平台的多媒體架構庫,主要是在gnome 基礎核心庫 glib 之上構建。下面有一個簡單的使用cgo 封裝 gstreamer playbin 外掛程式的例子: gstuse.go

package main/*#cgo pkg-config: gstreamer-1.0#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <gst/gst.h>void play(const char *uri){    GstElement *pipeline;    GstBus *bus;    GstMessage *msg;    gst_init (NULL, NULL);    char *res;    if (-1 == asprintf(&res, "playbin uri=%s", uri)){        return;    }    pipeline = gst_parse_launch(res, NULL);    if(!pipeline){        g_print("create playbin pipeline error\n");        free(res);        return;    }    gst_element_set_state (pipeline, GST_STATE_PLAYING);    bus = gst_element_get_bus (pipeline);    msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,                                  GST_MESSAGE_ERROR|GST_MESSAGE_EOS);    if (msg != NULL)        gst_message_unref (msg);    free(res);    gst_object_unref (bus);    gst_element_set_state (pipeline, GST_STATE_NULL);    gst_object_unref (pipeline);}*/import  "C"import "unsafe"func  sndply(snd string){    if  snd == ""{        return    }    cs := C.CString(snd)    defer  C.free(unsafe.Pointer(cs))    C.play(cs)}

把c 代碼寫在注釋之中,很像python/c 之間的 cffi  工具, #cgo 是cgo 工具的編譯指示標誌, pkg-config  指定所需連結的庫的元資訊, 標頭檔,庫位置等,

如果是平時跟c 代碼連結 一般這樣使用 pkg-config --cflags --libs  gstreamer-1.0, cgo 中只需要寫庫名字 。playbin 是gstreamer 的高層外掛程式, 提供媒體的播放功能, 它會自動建立ApsaraVideo for Media Processing管線, 尋找合適的demuxer,  decoder。

gst_parse_launch() 函數, 提供類似gst-lanch-×xx 命令列工具文法組建處理pipeline。 使用

gst_element_set_state

把pipeline 設定為啟動播放狀態,然後擷取pipeline的匯流排, 在匯流排上等待直到遇到錯誤,或者媒體流的末尾。

C.CString  把 golang  string 類型轉換*C.char , 其是在heap 上分配, 需要調用C.free  釋放。下面是使用金山詞霸api 的例子:

gciba.go

package mainimport (    "fmt"    "log"    "flag"    "sync"    "net/http"    "net/url"    "encoding/json")const  reqUri = "http://dict-co.iciba.com/api/dictionary.php?"type Dict struct {    Exchange struct {       Word_done string   `json:"word_done"`       Word_er   []string `json:"word_er"`       Word_est  []string `json:"word_est"`       Word_ing  string   `json:"word_ing"`       Word_past string   `json:"word_past"`       Word_pl   []string `json:"word_pl"`       Word_third  string `json:"word_third"`    }`json:"exchange"`    Iscri   int         `json:"is_CRI"`    Items  []string       `json:"items"`    Symbols []struct{        Parts []struct{            Means []string `json:"means"`            Part   string  `json:"part"`        }`json:"parts"`        Ph_am  string     `json:"ph_am"`        Ph_am_mp3 string  `json:"ph_am_mp3"`        Ph_en  string     `json:"ph_en"`        Ph_en_mp3 string  `json:"ph_en_mp3"`        Ph_other  string  `json:"ph_other"`        Ph_tts_mp3 string `json:"ph_tts_mp3"`    }`json:"symbols"`    Word_name  string     `json:"word_name"`}func player(snds chan string, done chan bool){     for s := range snds {         sndply(s)     }     close(done)}func doTrans(word string, snds chan string) {    defer  wg.Done()    reqArgs := url.Values{}    reqArgs.Add("w", word)    reqArgs.Add("type", "json")    reqArgs.Add("key", "E9E58402D44342EFB0B1ABC41E86BF8E")    resp, err := http.Get(reqUri + reqArgs.Encode())    if err != nil {        log.Println(err)        return    }    defer  resp.Body.Close()    var res Dict    enc := json.NewDecoder(resp.Body)    enc.Decode(&res)    //fmt.Println(res)    var  snd string    if  len(res.Symbols) < 1 { return  }    switch  *phonetic {    case "am":  snd = res.Symbols[0].Ph_am_mp3    case "en":  snd = res.Symbols[0].Ph_en_mp3    default :   snd = res.Symbols[0].Ph_tts_mp3    }    snds  <- snd    fmt.Printf("am: %s, en: %s\n", res.Symbols[0].Ph_am,                                   res.Symbols[0].Ph_en )    for  _, p := range  res.Symbols[0].Parts {        fmt.Printf("%s  %s\n", p.Part, p.Means)    }    fmt.Println()}var phonetic = flag.String("phon", "am", "use american or english phonetic")var  wg  sync.WaitGroupfunc  main() {    flag.Parse()    snds := make(chan string, flag.NArg())    done := make(chan bool)    go player(snds, done)    for _, w := range flag.Args(){        wg.Add(1)        go  doTrans(w, snds)    }    wg.Wait()    close(snds)    <-done}

player 函數包裹了gstuse.go 中的 sndply ,使用單獨的goroutine 調用 player函數,player 從 snds  channel 讀取聲音uri,直到channel 被關閉,close done channel, 通知main goroutine, 自己要退出。doTrans 發起web request, 解析包含json的結果,提取聲音uri  發到 snds channel。snds 是緩衝channel,也可改成無緩衝channel, 使得上一個單詞未發音之前,不得列印下一個單詞。

編譯 :    go build -o gciba gciba.go gstuse.go

./gciba  clear some thing chrome

am: kroʊm, en: krəʊm

n.  [Google瀏覽器 鉻,鉻合金]

vt.  [鍍以鉻 用鉻化合物印染]


am: θɪŋ, en: θɪŋ

n.  [事件,形勢 東西,事物 傢伙 事業]


am: sʌm, en: səm

adj.  [一些 某個 大約 相當多的]

pron.  [一些 若干 其中的一部分 (數量不確切時用)有些人]

adv.  [非常 相當 <美>稍微]


am: klɪr, en: klɪə(r)

adj.  [清楚的,明白的 清晰的,明亮的 清澈的 明確的]

adv.  [完全地 清晰地 整整]

vi.  [變明朗 變清澈]

vt.  [掃除,除去 消除(嫌疑) 使清楚 使乾淨]

n.  [空隙,空間]

cgo  調用也存在以些問題,由於所調用的c 庫由於設計上的問題, 使用 thread local storage或者某些api 不是thread safe ,導致不能並發使用,或者要鎖在特定線程之上。 minux 指出從 golang1.0 到 1.4  cgo 調用耗時越來越長。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.