詳解如何在Go語(yǔ)言中調(diào)用C源代碼_第1頁(yè)
詳解如何在Go語(yǔ)言中調(diào)用C源代碼_第2頁(yè)
詳解如何在Go語(yǔ)言中調(diào)用C源代碼_第3頁(yè)
詳解如何在Go語(yǔ)言中調(diào)用C源代碼_第4頁(yè)
詳解如何在Go語(yǔ)言中調(diào)用C源代碼_第5頁(yè)
全文預(yù)覽已結(jié)束

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第詳解如何在Go語(yǔ)言中調(diào)用C源代碼目錄開(kāi)坑說(shuō)明內(nèi)嵌形式外置的C代碼1.構(gòu)建libauth.a靜態(tài)庫(kù)2.對(duì)main.go稍加修改3.編譯

開(kāi)坑說(shuō)明

最近在編寫(xiě)客戶端程序或與其他部門(mén)做功能集成時(shí)多次碰到了跨語(yǔ)言的sdk集成,雖說(shuō)方案很多諸如rpc啊,管道啊,文件io啊,unixsocket啊之類的不要太多,但最完美的基礎(chǔ)方式還是讓程序與sdk結(jié)合到一起(個(gè)人觀點(diǎn),不喜勿噴),順便研究了下在go調(diào)用標(biāo)準(zhǔn)c接口的種種方法與坑,內(nèi)容不少,有空便慢慢更新了。

內(nèi)嵌形式

先讓我們來(lái)看一個(gè)最簡(jiǎn)單的cgo實(shí)例

packagemain

//#includestdio.h

import"C"

funcmain(){

C.puts(C.CString("HelloWorld"))

輸出

HelloWorld

通過(guò)C包調(diào)用了c中常見(jiàn)的puts函數(shù)同時(shí)傳入通過(guò)C.Cstring把go中string轉(zhuǎn)化為的cstring(相當(dāng)于char*)。其實(shí)C這個(gè)并不是一個(gè)包,而是通過(guò)importC語(yǔ)句啟用了go編譯器cgo相關(guān)的功能讓gcc也參與到了編譯中。這種方式通過(guò)緊貼在importC語(yǔ)句上面的注釋中編寫(xiě)c代碼并在后續(xù)代碼中使用C對(duì)象調(diào)用。當(dāng)然也可以通過(guò)這種方式調(diào)用自定義的c函數(shù)。

packagemain

import"C"

/*#includestdio.h

voidsay_hello_with_name(char*name){

printf("hello%s\n",name);

import"C"

funcmain(){

C.say_hello_with_name(C.CString("oscar"))

}

輸出

hellooscar

外置的C代碼

內(nèi)置的C代碼固然很方便,但用到cgo大多數(shù)的使用場(chǎng)景是我有一個(gè)需要復(fù)用的c代碼庫(kù),像是c++的stl庫(kù)亦或者是linuxc中的什么已經(jīng)封裝好的第三方依賴。這些時(shí)候便需要外置一些c的文件.h.c.cpp之類與.go文件混編。先看一個(gè)最簡(jiǎn)單的例子(調(diào)用linux的系統(tǒng)賬戶認(rèn)證)。

//auth.h

intauth(char*user,char*passwd);

//auth.c

#includeshadow.h

#includestdio.h

#includeunistd.h

intauth(char*user,char*passwd){

char*obtpwd;

structspwd*spasswd;

spasswd=getspnam(user);

obtpwd=crypt(passwd,spasswd-sp_pwdp);

if(strcmp(spasswd-sp_pwdp,obtpwd)==0)

return0;

elsereturn1;

}

//main.go

packagemain

#cgoLDFLAGS:-lcrypt

#include"auth.h"

import"C"

import"fmt"

funcmain(){

varusername,passwordstring

fmt.Println("Pleaseenteryourusernameandpassword:")

_,_=fmt.Scanln(username,password)

rst:=C.auth(C.CString(username),C.CString(password))

fmt.Println(rst)

}

保證上述三個(gè)文件在同一個(gè)go工程目錄下運(yùn)行g(shù)obuild-omain構(gòu)建工程。#cgoLDFLAGS:-lcrypt這個(gè)一行是cgo給gcc的編譯參數(shù),相關(guān)的編譯參數(shù)與連接參數(shù)有空了在后面的文章里說(shuō)明,-lcrypt表示編譯時(shí)需要去連接libcrypt這個(gè)庫(kù)。

注意,這種cgo混編的方式個(gè)人是不建議的,cgo對(duì)外置c代碼片構(gòu)建支持非常差,我無(wú)法在cgo中通過(guò)編譯參數(shù)指定c代碼片的搜索路徑(頭文件倒是沒(méi)啥問(wèn)題),這也就意味著當(dāng)項(xiàng)目被調(diào)用的c代碼片都得在項(xiàng)目根目錄下,這可太糟糕了。個(gè)人覺(jué)得如果有大量的外部依賴c語(yǔ)言的庫(kù)請(qǐng)分開(kāi)編譯,c庫(kù)使用gcc編譯成靜態(tài)或動(dòng)態(tài)庫(kù)在讓go在編譯時(shí)連接為好,寫(xiě)個(gè)makefile分開(kāi)分步編譯也不是什么麻煩事,還是上面的例子,讓我們把編譯的過(guò)程稍加修改。

1.構(gòu)建libauth.a靜態(tài)庫(kù)

gcc-c-oauth.o-lcryptauth.c

arrcslibauth.aauth.o

得到libauth.a

2.對(duì)main.go稍加修改

packagemain

#cgoCFLAGS:-I./

#cgoLDFLAGS:-L.-lauth-lcrypt

#include"auth.h"

import"C"

import"fmt"

funcmain(){

varusername,passwordstring

fmt.Println("Pleaseenteryourusernameandpassword:")

_,_=fmt.Scanln(username,password)

rst:=C.auth(C.CString(username),C.CString(password))

fmt.Println(rst)

此處修改主要是新增了libauth.a靜態(tài)庫(kù)的鏈接參數(shù)

3.編譯

gobuild-omainmain.go

可以把上述的步驟整下寫(xiě)個(gè)簡(jiǎn)單的makefile

.PHONY:all

all:main

libauth.a:auth.c

gcc-c-oauth.o-lcryptauth.c

arr

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論