文章系列
【GO】Golang/C++混合編程 - SWIG
【GO】Golang/C++混合編程 - 初識
【GO】Golang/C++混合編程 - 入門
【GO】Golang/C++混合編程 - 基礎(chǔ)
【GO】Golang/C++混合編程 - 進階一
【GO】Golang/C++混合編程 - 進階二
【GO】Golang/C++混合編程 - 實戰(zhàn)
Golang/C++混合編程
依賴安裝
要使用CGO特性,需要安裝C/C++構(gòu)建工具鏈缭黔,在macOS和Linux下是要安裝GCC宴胧,在windows下是需要安裝MinGW工具。
同時需要保證環(huán)境變量CGO_ENABLED被設(shè)置為1扒接,這表示CGO是被啟用的狀態(tài)。在本地構(gòu)建時CGO_ENABLED默認(rèn)是啟用的们衙,當(dāng)交叉構(gòu)建時CGO默認(rèn)是禁止的钾怔。
比如要交叉構(gòu)建ARM環(huán)境運行的Go程序,需要手工設(shè)置好C/C++交叉構(gòu)建的工具鏈蒙挑,同時開啟CGO_ENABLED環(huán)境變量宗侦。然后通過import "C"語句啟用CGO特性。
使用方式
內(nèi)嵌C代碼
在Go文件中忆蚀,通過import "C"語句來引入C代碼矾利,C代碼可以寫在Go文件中,也可以單獨放在一個.h和.c文件中馋袜,然后在Go文件中通過
#include
來引用男旗。
package main
/*
#include <stdio.h>
void hello() {
printf("Hello, World!\n");
}
*/
import "C"
func main() {
C.hello()
}
內(nèi)嵌C++代碼(使用extern "C")
在Go文件中,通過import "C"語句來引入C++代碼欣鳖,C++代碼可以寫在Go文件中察皇,也可以單獨放在一個.h和.cpp文件中,然后在Go文件中通過
#include
來引用泽台。
package main
/*
extern "C" {
#include <iostream>
void hello() {
std::cout << "Hello, World!" << std::endl;
}
}
*/
import "C"
func main() {
C.hello()
}
使用C靜態(tài)庫/動態(tài)庫
在Go文件中什荣,通過import "C"語句來引入C/C++代碼,C/C++代碼可以寫在Go文件中怀酷,也可以單獨放在一個.h和.c/.cpp文件中溃睹,然后在Go文件中通過
#include
來引用。使用CFLAGS/CPPFLAGS/CXXFLAGS和LDFLAGS來指定頭文件路徑和庫文件路徑胰坟。注:其中CFLAGS對應(yīng)C語言編譯參數(shù)(以.c后綴名)因篇、CPPFLAGS對應(yīng)C/C++ 代碼編譯參數(shù)(.c,.cc,.cpp,.cxx)、CXXFLAGS對應(yīng)純C++編譯參數(shù)(.cc,.cpp,*.cxx)笔横。LDFLAGS指定庫文件時竞滓,只需要加前綴
-l
和庫名即可,其中 linux/macos 下庫多為 xxx.a, xxx.so; windows多為 xxx.lib, xxx.dll吹缔。
package main
/*
#cgo CFLAGS: -I. -I./include
#cgo LDFLAGS: -L. -lmylib
#include <stdio.h>
#include "mylib.h"
void hello() {
printf("Hello, World!\n");
}
*/
import "C"
func main() {
C.hello()
}
使用C++靜態(tài)庫/動態(tài)庫
由于 CGO 是 C 語言和 GO GO 無法直接使用 C++ 靜態(tài)庫和動態(tài)庫商佑。所以此時需要實現(xiàn)一組 C 語言函數(shù)接口作為 C++類和 CGO 之間的橋梁, 其命名規(guī)則多為 xxx_bridge.h/xxx_bridge.cpp。
以下為一個簡單示例厢塘,默認(rèn)已存在 libhello.a 庫文件茶没,其中包含一個函數(shù) void hello()肌幽,功能為打印一個字符串“hello”。
// hello_bridge.h
#ifndef _HELLO_H_
#define _HELLO_H_
#ifdef __cplusplus
extern "C" {
#endif
void Hello();
#ifdef __cplusplus
}
#endif
#endif // _HELLO_H_
// hello_bridge.cpp
#include "hello_bridge.h"
#include "hello.h"
void Hello() {
hello();
}
// main.go
package main
/*
#cgo CXXFLAGS: -std=c++11
#cgo CXXFLAGS: -I. -I./include
#cgo LDFLAGS: -L. -lhello
#include "hello_bridge.h"
*/
import "C"
func main() {
C.Hello()
}
# 運行程序
$ go run .
使用 pkg-config
pkg-config 是一個用于管理編譯器和鏈接器選項的工具抓半,它可以幫助我們自動找到庫文件和頭文件的位置喂急。使用 pkg-config 可以避免手動指定頭文件路徑和庫文件路徑,簡化了編譯和鏈接的過程笛求。
后續(xù)補充...