Go?語(yǔ)言中運(yùn)行?C程序?代碼?
前言:
在前面多篇 Go 系列文章中,我們了解到,Go 語(yǔ)言脫胎于 C 語(yǔ)言,這就意味著在某些更底層的細(xì)節(jié)中,我們可以使用 C 語(yǔ)言實(shí)現(xiàn),然后通過(guò) Go 來(lái)調(diào)用相關(guān)的 C 代碼。其實(shí)這一特點(diǎn),在 Java 的 JVM、Python 的解釋器也是通過(guò)底層是直接調(diào)用 C 實(shí)現(xiàn)的。
而本篇文章就來(lái)學(xué)習(xí)一下,如何在 Go 語(yǔ)言中運(yùn)行 C 程序。
一、直接在 Go 代碼中寫(xiě)入 C 程序
Go 語(yǔ)言通過(guò) cgo 工具來(lái)識(shí)別代碼中的 C 語(yǔ)言,我們可以通過(guò)命令 ??go env?? 來(lái)查看是否 cgo 工具是否開(kāi)啟。

??CGO_ENABLED=1?? 表示 cgo 工具可用,當(dāng)設(shè)置為 0 時(shí),表示工具不可用。
然后我可以新建一個(gè)??CinGo.go??? 的程序,然后在注釋中寫(xiě)入 c 語(yǔ)言的代碼。然后導(dǎo)入 Go 提供的 c 包 ??import "C"?? ,Go 語(yǔ)言在看到導(dǎo)入這個(gè)包之后就知道如何去處理注釋中的內(nèi)容了。
這里我們?cè)?C 代碼中寫(xiě)入要給 ??callC()?? 函數(shù),然后在 Go 語(yǔ)言中進(jìn)行調(diào)用:
package main
// #include <stdio.h>
// void callC() {
// ? printf("Hello World from C!\n");
// }
import "C"
import "fmt"
func main() {
? fmt.Println("讓我們學(xué)習(xí) Go 語(yǔ)句調(diào)用 C 程序")
? C.callC()
? fmt.Println("調(diào)用 C 程序結(jié)束")
}執(zhí)行結(jié)果:
$ go run CinGo.go
讓我們學(xué)習(xí) Go 語(yǔ)句調(diào)用 C 程序
Hello World from C!;'/;'
調(diào)用 C 程序結(jié)束
但是,這種方式的 C 代碼和 Go 語(yǔ)言代碼在同一個(gè)文件中,所以大家能明顯發(fā)現(xiàn)這種方式的代碼耦合度太高,僅僅適用于項(xiàng)目簡(jiǎn)單單一的情形。
一個(gè)更合理的方式應(yīng)該是 C 代碼單獨(dú)在一個(gè)文件。
二、Go 直接調(diào)用 C 文件
那么,如果已經(jīng)寫(xiě)好一個(gè)封裝好的 C 文件代碼,Go 語(yǔ)言該如何調(diào)用呢?
此時(shí)我們需要直接寫(xiě)好 C 代碼,因?yàn)?Go 代碼是無(wú)法對(duì) C 代碼文件進(jìn)行重寫(xiě)或者修改的。
?寫(xiě)好 C 頭文件?
我們?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
?編寫(xiě) C 文件?
然后編寫(xiě) ??hello.c?? 文件,如下:
#include "hello.h"
#include <stdio.h>
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 語(yǔ)言接收的信息: %s\n", message);
}
int add(int a, int b) {
? ? return a + b;
}?寫(xiě)好 Go 代碼?
最后編寫(xiě)我們的 ??main.go?? 語(yǔ)言:
- 我們需要在 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 <stdlib.h>
// #include <hello.h>
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 語(yǔ)言接收的信息: This is Go
總結(jié):
在編寫(xiě)上述的小案例過(guò)程你中的,都出現(xiàn)了了很多小問(wèn)題,比如 C 代碼和 ??import "c"?? 語(yǔ)句之間不能有空格。經(jīng)常會(huì)出現(xiàn)找不到 C 函數(shù)等等問(wèn)題。
?總得來(lái)說(shuō),日常 Go 開(kāi)發(fā)還是不需要此類(lèi)高級(jí)用法,也就是說(shuō)其實(shí)我們平常編程過(guò)程中不太需要 cgo,大多數(shù)情況下還是盡量用 Go 語(yǔ)言自己實(shí)現(xiàn)。如果確實(shí)需要使用 C 語(yǔ)言,還是得多去了解 ? ?cgo?? 的文檔,以防出錯(cuò)。
到此這篇關(guān)于Go 語(yǔ)言中運(yùn)行 C程序 代碼 的文章就介紹到這了,更多相關(guān)Go中運(yùn)行 C 代碼 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go高效率開(kāi)發(fā)Web參數(shù)校驗(yàn)三種方式實(shí)例
這篇文章主要介紹了Go高效率開(kāi)發(fā)Web參數(shù)校驗(yàn)三種方式實(shí)例,需要的朋友可以參考下2022-11-11
Go調(diào)用opencv實(shí)現(xiàn)圖片矯正的代碼示例
這篇文章主要為大家詳細(xì)介紹了Go調(diào)用opencv實(shí)現(xiàn)圖片矯正的代碼示例,文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-09-09
go代碼實(shí)現(xiàn)買(mǎi)房貸款月供計(jì)算的方法
今天小編就為大家分享一篇關(guān)于go代碼實(shí)現(xiàn)買(mǎi)房貸款月供計(jì)算的方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-04-04
Go語(yǔ)言操作數(shù)據(jù)庫(kù)及其常規(guī)操作的示例代碼
這篇文章主要介紹了Go語(yǔ)言操作數(shù)據(jù)庫(kù)及其常規(guī)操作的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
Golang觀察者模式優(yōu)化訂單處理系統(tǒng)實(shí)例探究
當(dāng)涉及到訂單處理系統(tǒng)時(shí),觀察者設(shè)計(jì)模式可以用于實(shí)現(xiàn)訂單狀態(tài)的變化和通知,在這篇文章中,我們將介紹如何使用Golang來(lái)實(shí)現(xiàn)觀察者設(shè)計(jì)模式,并提供一個(gè)基于訂單處理系統(tǒng)的代碼示例2024-01-01

