欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

開坑說明

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

內(nèi)嵌形式

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

package main

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

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

輸出

Hello World

通過"C包"調(diào)用了c中常見的puts函數(shù)同時(shí)傳入通過C.Cstring把go 中string轉(zhuǎn)化為的c string(相當(dāng)于char *)。其實(shí)“C”這個(gè)并不是一個(gè)包,而是通過import "C"語句啟用了go編譯器cgo相關(guān)的功能讓gcc也參與到了編譯中。這種方式通過緊貼在import "C"語句上面的注釋中編寫c代碼并在后續(xù)代碼中使用C對(duì)象調(diào)用。當(dāng)然也可以通過這種方式調(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ù)有空了在后面的文章里說明,-lcrypt 表示編譯時(shí)需要去連接libcrypt這個(gè)庫(kù)。
注意,這種c go 混編的方式個(gè)人是不建議的,cgo對(duì)外置c代碼片構(gòu)建支持非常差,我無法在cgo中通過編譯參數(shù)指定c代碼片的搜索路徑(頭文件倒是沒啥問題),這也就意味著當(dāng)項(xiàng)目被調(diào)用的c代碼片都得在項(xiàng)目根目錄下,這可太糟糕了。個(gè)人覺得如果有大量的外部依賴c語言的庫(kù)請(qǐng)分開編譯,c庫(kù)使用gcc編譯成靜態(tài)或動(dòng)態(tài)庫(kù)在讓go在編譯時(shí)連接為好,寫個(gè)makefile分開分步編譯也不是什么麻煩事,還是上面的例子,讓我們把編譯的過程稍加修改。

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)物的過程變得相對(duì)簡(jiǎn)單快捷

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

相關(guān)文章

  • 示例剖析golang中的CSP并發(fā)模型

    示例剖析golang中的CSP并發(fā)模型

    這篇文章主要為大家介紹了示例剖析golang中的CSP并發(fā)模型,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • goland 清除所有的默認(rèn)設(shè)置操作

    goland 清除所有的默認(rèn)設(shè)置操作

    這篇文章主要介紹了goland 清除所有的默認(rèn)設(shè)置操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Golang極簡(jiǎn)入門教程(四):編寫第一個(gè)項(xiàng)目

    Golang極簡(jiǎn)入門教程(四):編寫第一個(gè)項(xiàng)目

    這篇文章主要介紹了Golang極簡(jiǎn)入門教程(四):編寫第一個(gè)項(xiàng)目,本文講解了workspace、包路徑、第一個(gè)可執(zhí)行命令等內(nèi)容,需要的朋友可以參考下
    2014-10-10
  • Golang學(xué)習(xí)筆記之安裝Go1.15版本(win/linux/macos/docker安裝)

    Golang學(xué)習(xí)筆記之安裝Go1.15版本(win/linux/macos/docker安裝)

    這篇文章主要介紹了Golang學(xué)習(xí)筆記之安裝Go1.15版本(win/linux/macos/docker安裝),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • 揭秘Go語言中的反射機(jī)制

    揭秘Go語言中的反射機(jī)制

    在Go語言中,反射是通過reflect包來實(shí)現(xiàn)的,通過使用反射,我們可以在運(yùn)行時(shí)獲取對(duì)象的類型信息、訪問對(duì)象的字段和方法、動(dòng)態(tài)調(diào)用方法等,反射在很多場(chǎng)景下都非常有用,比如編寫通用的代碼、實(shí)現(xiàn)對(duì)象的序列化和反序列化、實(shí)現(xiàn)依賴注入等,需要的朋友可以參考下
    2023-10-10
  • Go語言利用接口實(shí)現(xiàn)鏈表插入功能詳解

    Go語言利用接口實(shí)現(xiàn)鏈表插入功能詳解

    這篇文章主要為大家介紹了Go語言中的接口,以及如何利用接口實(shí)現(xiàn)鏈表插入功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-04-04
  • 淺談Go語言中的次方用法

    淺談Go語言中的次方用法

    這篇文章主要介紹了淺談Go語言中的次方用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang利用Recover進(jìn)行錯(cuò)誤處理

    Golang利用Recover進(jìn)行錯(cuò)誤處理

    Golang?中的?recover?是一個(gè)鮮為人知但非常有趣和強(qiáng)大的功能,這篇文章小編就來帶大家深入了解一下在Golang中是如何利用Recover進(jìn)行錯(cuò)誤處理吧
    2023-12-12
  • 詳解Golang中interface{}的注意事項(xiàng)

    詳解Golang中interface{}的注意事項(xiàng)

    學(xué)習(xí)?golang?,對(duì)于?interface{}?接口類型,我們一定繞不過,這篇文章咱們就來一起來看看?使用?interface{}?的時(shí)候,都有哪些注意事項(xiàng)吧
    2023-03-03
  • 詳細(xì)介紹Go語言之?dāng)?shù)組與切片

    詳細(xì)介紹Go語言之?dāng)?shù)組與切片

    這篇文章介紹Go語言之?dāng)?shù)組與切片,數(shù)組是具有相同唯一類型的一組已編號(hào)且長(zhǎng)度固定的數(shù)據(jù)項(xiàng)序列,這種類型可是任意的原始類型如整形、字符串或自定義類型。切片是數(shù)組的一個(gè)引用,因此切片是引用類型,在進(jìn)行傳遞時(shí),遵守引用傳遞的機(jī)制,下面我們就來詳細(xì)了解一下該內(nèi)容
    2021-10-10

最新評(píng)論