Go?語言中運行?C程序?代碼?
前言:
在前面多篇 Go 系列文章中,我們了解到,Go 語言脫胎于 C 語言,這就意味著在某些更底層的細節(jié)中,我們可以使用 C 語言實現(xiàn),然后通過 Go 來調用相關的 C 代碼。其實這一特點,在 Java 的 JVM、Python 的解釋器也是通過底層是直接調用 C 實現(xiàn)的。
而本篇文章就來學習一下,如何在 Go 語言中運行 C 程序。
一、直接在 Go 代碼中寫入 C 程序
Go 語言通過 cgo 工具來識別代碼中的 C 語言,我們可以通過命令 ??go env?? 來查看是否 cgo 工具是否開啟。
??CGO_ENABLED=1
?? 表示 cgo 工具可用,當設置為 0 時,表示工具不可用。
然后我可以新建一個??CinGo.go???
的程序,然后在注釋中寫入 c 語言的代碼。然后導入 Go 提供的 c 包 ??import "C"?? ,Go 語言在看到導入這個包之后就知道如何去處理注釋中的內容了。
這里我們在 C 代碼中寫入要給 ??callC()?? 函數(shù),然后在 Go 語言中進行調用:
package main // #include <stdio.h> // void callC() { // ? printf("Hello World from C!\n"); // } import "C" import "fmt" func main() { ? fmt.Println("讓我們學習 Go 語句調用 C 程序") ? C.callC() ? fmt.Println("調用 C 程序結束") }
執(zhí)行結果:
$ go run CinGo.go
讓我們學習 Go 語句調用 C 程序
Hello World from C!;'/;'
調用 C 程序結束
但是,這種方式的 C 代碼和 Go 語言代碼在同一個文件中,所以大家能明顯發(fā)現(xiàn)這種方式的代碼耦合度太高,僅僅適用于項目簡單單一的情形。
一個更合理的方式應該是 C 代碼單獨在一個文件。
二、Go 直接調用 C 文件
那么,如果已經寫好一個封裝好的 C 文件代碼,Go 語言該如何調用呢?
此時我們需要直接寫好 C 代碼,因為 Go 代碼是無法對 C 代碼文件進行重寫或者修改的。
?寫好 C 頭文件?
我們在本地 Go 項目中,創(chuàng)建一個 ??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 <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 語言接收的信息: %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 <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) }
?最后代碼結構如下:
然后我們首先編譯 c 代碼:
$ gcc -c *.c ? ? ? $ /usr/bin/ar rs hello.a *.o ar: creating archive hello.a $ rm hello.o
然后再執(zhí)行 Go 代碼,結果如下:
$ go run main.go ? ? ? ?? Hello from C! Reuslt is: 3046
從 Go 語言接收的信息: This is Go
總結:
在編寫上述的小案例過程你中的,都出現(xiàn)了了很多小問題,比如 C 代碼和 ??import "c"?? 語句之間不能有空格。經常會出現(xiàn)找不到 C 函數(shù)等等問題。
?總得來說,日常 Go 開發(fā)還是不需要此類高級用法,也就是說其實我們平常編程過程中不太需要 cgo,大多數(shù)情況下還是盡量用 Go 語言自己實現(xiàn)。如果確實需要使用 C 語言,還是得多去了解 ? ?cgo?? 的文檔,以防出錯。
到此這篇關于Go 語言中運行 C程序 代碼 的文章就介紹到這了,更多相關Go中運行 C 代碼 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Go語言操作數(shù)據(jù)庫及其常規(guī)操作的示例代碼
這篇文章主要介紹了Go語言操作數(shù)據(jù)庫及其常規(guī)操作的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-04-04Golang觀察者模式優(yōu)化訂單處理系統(tǒng)實例探究
當涉及到訂單處理系統(tǒng)時,觀察者設計模式可以用于實現(xiàn)訂單狀態(tài)的變化和通知,在這篇文章中,我們將介紹如何使用Golang來實現(xiàn)觀察者設計模式,并提供一個基于訂單處理系統(tǒng)的代碼示例2024-01-01