如何在 Go 代碼中運(yùn)行 C 語言代碼

      網(wǎng)友投稿 912 2025-03-31

      前言

      在前面多篇 Go 系列文章中,我們了解到,Go 語言脫胎于 C 語言,這就意味著在某些更底層的細(xì)節(jié)中,我們可以使用 C 語言實(shí)現(xiàn),然后通過 Go 來調(diào)用相關(guān)的 C 代碼。其實(shí)這一特點(diǎn),在 Java 的 JVM、Python 的解釋器也是通過底層是直接調(diào)用 C 實(shí)現(xiàn)的。

      而本篇文章就來學(xué)習(xí)一下,如何在 Go 語言中運(yùn)行 C 程序。

      直接在 Go 代碼中寫入 C 程序

      Go 語言通過 cgo 攻擊來識別代碼中的 C 語言,我們可以通過命令 go env 來查看是否 cgo 工具是否開啟。

      CGO_ENABLED=1 表示 cgo 工具可用,當(dāng)設(shè)置為 0 時(shí),表示工具不可用。

      然后我可以新建一個(gè) CinGo.go 的程序,然后在注釋中寫入 c 語言的代碼。然后導(dǎo)入 Go 提供的 c 包 import "C" ,Go 語言在看到導(dǎo)入這個(gè)包之后就知道如何去處理注釋中的內(nèi)容了。

      這里我們在 C 代碼中寫入要給 callC() 函數(shù),然后在 Go 語言中進(jìn)行調(diào)用:

      package main // #include // void callC() { // printf("Hello World from C!\n"); // } import "C" import "fmt" func main() { fmt.Println("讓我們學(xué)習(xí) Go 語句調(diào)用 C 程序") C.callC() fmt.Println("調(diào)用 C 程序結(jié)束") }

      執(zhí)行結(jié)果:

      $ go run CinGo.go 讓我們學(xué)習(xí) Go 語句調(diào)用 C 程序 Hello World from C! 調(diào)用 C 程序結(jié)束

      但是,這種方式的 C 代碼和 Go 語言代碼在同一個(gè)文件中,所以大家能明顯發(fā)現(xiàn)這種方式的代碼耦合度太高,僅僅適用于項(xiàng)目簡單單一的情形。

      一個(gè)更合理的方式應(yīng)該是 C 代碼單獨(dú)在一個(gè)文件。

      Go 直接調(diào)用 C 文件

      那么,如果已經(jīng)寫好一個(gè)封裝好的 C 文件代碼,Go 語言該如何調(diào)用呢?

      此時(shí)我們需要直接寫好 C 代碼,因?yàn)?Go 代碼是無法對 C 代碼文件進(jìn)行重寫或者修改的。

      寫好 C 頭文件

      我們在本地 Go 項(xiàng)目中,創(chuàng)建一個(gè) hello.h 的頭文件,代碼如下:

      #ifndef HELLO_H #define HELLO_H int sayHello(const char *name, char *out); void printMessage(char *message); void cHello(); int add(int a, int b); #endif

      編寫 C 文件

      然后編寫 hello.c 文件,如下:

      #include "hello.h" #include int sayHello(const char *name, char *out) { int n; n = sprintf(out, "Hello, My name is %s!", name); return n; } void cHello() { printf("Hello from C!\n"); } void printMessage(char* message) { printf("從 Go 語言接收的信息: %s\n", message); } int add(int a, int b) { return a + b; }

      寫好 Go 代碼

      最后編寫我們的 main.go 語言:

      我們需要在 CFLAGS 參數(shù)中填入我們的 GOPath 路徑, #cgo CFLAGS: -I /Users/yuzhou_1su/go/src/CinGo ?。

      然后在 LSFLAGS 中填入我們的 C 編譯后的本地鏈接文件: #cgo LDFLAGS: /Users/yuzhou_1su/go/src/CinGo/hello.a

      package main // #cgo CFLAGS: -I /Users/yuzhou_1su/go/src/CinGo // #cgo LDFLAGS: /Users/yuzhou_1su/go/src/CinGo/hello.a // #include // #include import "C" import ( "fmt" "unsafe" ) func main() { C.cHello() a := C.int(1024) b := C.int(2022) result := C.add(a, b) fmt.Println("Reuslt is:", result) goMessage := C.CString("This is Go") defer C.free(unsafe.Pointer(goMessage)) C.printMessage(goMessage) }

      最后代碼結(jié)構(gòu)如下:

      然后我們首先編譯 c 代碼:

      $ gcc -c *.c $ /usr/bin/ar rs hello.a *.o ar: creating archive hello.a $ rm hello.o

      然后再執(zhí)行 Go 代碼,結(jié)果如下:

      $ go run main.go Hello from C! Reuslt is: 3046 從 Go 語言接收的信息: This is Go

      總結(jié)

      在編寫上述的小案例過程你中的,都出現(xiàn)了了很多小問題,比如 C 代碼和 import "c" ? 語句之間不能有空格。經(jīng)常會出現(xiàn)找不到 C 函數(shù)等等問題。

      總得來說,日常 Go 開發(fā)還是不需要此類高級用法,也就是說其實(shí)我們平常編程過程中不太需要 cgo,大多數(shù)情況下還是盡量用 Go 語言自己實(shí)現(xiàn)。如果確實(shí)需要使用 C 語言,還是得多去了解 cgo 的文檔,以防出錯(cuò)。

      如何在 Go 代碼中運(yùn)行 C 語言代碼

      靈感來源:

      Calling C code from go | Karthik Karanth

      https://pkg.go.dev/cmd/cgo

      精通 Go 語言

      C 語言 Go HTTP

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:excel甘特圖制作方法,怎么用excel做甘特圖
      下一篇:excel 截取(excel截取字段)
      相關(guān)文章
      亚洲AV无码乱码精品国产| 亚洲福利中文字幕在线网址| 国产成A人亚洲精V品无码| 亚洲中文无韩国r级电影| 国产精品亚洲综合网站| 老牛精品亚洲成av人片| 久久亚洲最大成人网4438| 亚洲制服丝袜第一页| 亚洲人成在线免费观看| 亚洲人成电影在线观看网| 亚洲精品在线播放| 亚洲春色在线观看| 亚洲一区在线观看视频| 精品亚洲AV无码一区二区| 国产成人精品日本亚洲专| 色婷五月综激情亚洲综合| 亚洲日韩中文字幕一区| 亚洲欧美日韩综合久久久久| 亚洲国产成人AV在线播放| 无码亚洲成a人在线观看| 国产成人亚洲精品播放器下载| 最新亚洲人成无码网www电影| 国产精品亚洲色婷婷99久久精品| 亚洲国产精品碰碰| 亚洲综合无码AV一区二区| 久久99国产亚洲高清观看首页 | 亚洲七久久之综合七久久| 亚洲国产欧美一区二区三区| 国产精品亚洲专区一区| 亚洲免费日韩无码系列| 亚洲午夜国产精品无码老牛影视 | 亚洲AV无码专区在线亚| 亚洲免费福利在线视频| 亚洲精品动漫免费二区| 亚洲VA综合VA国产产VA中| 国产AV无码专区亚洲AWWW | 亚洲伊人久久大香线蕉AV| 久久久久亚洲国产AV麻豆| 亚洲国产天堂久久久久久| 亚洲成a人片在线观看无码| 亚洲自偷精品视频自拍|