最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解如何在Go語(yǔ)言中調(diào)用C源代碼

 更新時(shí)間:2022年05月07日 15:38:10   作者:神王攻大人  
這篇文章主要為大家詳細(xì)介紹了如何在Go語(yǔ)言中調(diào)用C語(yǔ)言源代碼,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定的幫助,需要的可以參考一下

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

最近在編寫客戶端程序或與其他部門做功能集成時(shí)多次碰到了跨語(yǔ)言的sdk集成,雖說(shuō)方案很多諸如rpc啊,管道啊,文件io啊,unix socket啊之類的不要太多,但最完美的基礎(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í)例

package main

//#include <stdio.h>
import "C"

func main() {
	C.puts(C.CString("Hello World"))
}

輸出

Hello World

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

package main
import "C"

/*#include <stdio.h>

void say_hello_with_name(char * name){
	printf("hello %s\n", name);
}
 */
import "C"

func main() {
	C.say_hello_with_name(C.CString("oscar"))
}

輸出

hello oscar

外置的C代碼

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

// auth.h
int auth(char *user, char *passwd);
// auth.c
#include <shadow.h>
#include <stdio.h>
#include <unistd.h>

int auth(char *user, char *passwd){
    char *obtpwd;
    struct spwd *spasswd;

    spasswd = getspnam(user);
    obtpwd = crypt(passwd, spasswd->sp_pwdp);
    if(strcmp(spasswd->sp_pwdp, obtpwd) == 0)
    return 0;
    else return 1;
}
// main.go
package main

/*
#cgo LDFLAGS: -lcrypt

#include "auth.h"
*/
import "C"
import "fmt"

func main() {
	var username, password string

	fmt.Println("Please enter your username and password: ")
    _, _ = fmt.Scanln(&username, &password)

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

保證上述三個(gè)文件在同一個(gè)go工程目錄下運(yùn)行 go build -o main 構(gòu)建工程。#cgo LDFLAGS: -lcrypt 這個(gè)一行是cgo給gcc的編譯參數(shù),相關(guān)的編譯參數(shù)與連接參數(shù)有空了在后面的文章里說(shuō)明,-lcrypt 表示編譯時(shí)需要去連接libcrypt這個(gè)庫(kù)。
注意,這種c go 混編的方式個(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í)連接為好,寫個(gè)makefile分開(kāi)分步編譯也不是什么麻煩事,還是上面的例子,讓我們把編譯的過(guò)程稍加修改。

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

gcc -c -o auth.o -lcrypt auth.c
ar rcs libauth.a auth.o

得到libauth.a

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

package main

/*
#cgo CFLAGS: -I./
#cgo LDFLAGS: -L. -lauth -lcrypt

#include "auth.h"
*/
import "C"
import "fmt"

func main() {
	var username, password string

	fmt.Println("Please enter your username and password: ")
    _, _ = fmt.Scanln(&username, &password)

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

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

3. 編譯

go build -o main main.go

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

.PHONY : all

all: main

libauth.a: auth.c
	gcc -c -o auth.o -lcrypt auth.c
	ar rcs libauth.a auth.o

main: main.go libauth.a
	go build -o main main.go

clean:
	rm -f auth.o libauth.a main

這樣也讓我們得出產(chǎn)物的過(guò)程變得相對(duì)簡(jiǎn)單快捷

到此這篇關(guān)于詳解如何在Go語(yǔ)言中調(diào)用C源代碼的文章就介紹到這了,更多相關(guān)Go調(diào)用C源代碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • go語(yǔ)言?http模型reactor示例詳解

    go語(yǔ)言?http模型reactor示例詳解

    這篇文章主要介紹了go語(yǔ)言?http模型reactor,接下來(lái)看一段基于reactor的示例,這里運(yùn)行通過(guò)?go?run?main.go,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • Go語(yǔ)言學(xué)習(xí)教程之指針的示例詳解

    Go語(yǔ)言學(xué)習(xí)教程之指針的示例詳解

    這篇文章主要通過(guò)簡(jiǎn)單的練習(xí)來(lái)讓大家對(duì)Go語(yǔ)言中的指針有所了解,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定幫助,需要的可以參考一下
    2022-09-09
  • Golang time.Sleep()用法及示例講解

    Golang time.Sleep()用法及示例講解

    Go語(yǔ)言中的Sleep()函數(shù)用于在至少規(guī)定的持續(xù)時(shí)間d內(nèi)停止最新的go-routine,這篇文章主要介紹了Golang time.Sleep()用法及示例講解,需要的朋友可以參考下
    2023-02-02
  • Go批量操作excel導(dǎo)入到mongodb的技巧

    Go批量操作excel導(dǎo)入到mongodb的技巧

    這篇文章主要介紹了Go批量操作excel導(dǎo)入到mongo,包括選擇命令行包,讀取配置連接數(shù)據(jù)庫(kù)的方法,本文示例代碼相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-03-03
  • Go語(yǔ)言常見(jiàn)錯(cuò)誤接口污染解決分析

    Go語(yǔ)言常見(jiàn)錯(cuò)誤接口污染解決分析

    這篇文章主要為大家介紹了Go語(yǔ)言常見(jiàn)錯(cuò)誤接口污染解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • 使用Go?goroutine實(shí)現(xiàn)并發(fā)的Clock服務(wù)

    使用Go?goroutine實(shí)現(xiàn)并發(fā)的Clock服務(wù)

    這篇文章主要為大家詳細(xì)介紹了如何使用Go?goroutine實(shí)現(xiàn)并發(fā)的Clock服務(wù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-06-06
  • 一文帶你熟悉Go語(yǔ)言中函數(shù)的使用

    一文帶你熟悉Go語(yǔ)言中函數(shù)的使用

    這篇文章主要和大家分享一下Go語(yǔ)言中的函數(shù)的使用,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的小伙伴可以參考一下
    2022-11-11
  • go code review 代碼調(diào)試

    go code review 代碼調(diào)試

    這篇文章主要為大家介紹了go code review 代碼調(diào)試方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Go語(yǔ)言拼接URL路徑的三種方法

    Go語(yǔ)言拼接URL路徑的三種方法

    本文主要介紹了Go語(yǔ)言拼接URL路徑的三種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • 初步解讀Golang中的接口相關(guān)編寫方法

    初步解讀Golang中的接口相關(guān)編寫方法

    這篇文章主要介紹了Golang中的接口相關(guān)編寫方法,是Go語(yǔ)言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-11-11

最新評(píng)論

新安县| 灌阳县| 襄城县| 辽中县| 武宁县| 雷州市| 龙胜| 昆山市| 漯河市| 天长市| 平顶山市| 正宁县| 多伦县| 鄂托克前旗| 北宁市| 七台河市| 太和县| 达日县| 搜索| 临城县| 中宁县| 广元市| 松滋市| 乌拉特中旗| 长治县| 昭通市| 双峰县| 福建省| 西城区| 濮阳市| 朝阳县| 宽城| 苍梧县| 抚顺市| 临湘市| 友谊县| 天祝| 溆浦县| 文安县| 封开县| 澜沧|