在嵌入式開發中總少不了和C/C++打交道,而在開發中也總有某些需求要用到某些其他工具的特性,比如go語言。
Go語言專門針對多處理器系統應用程序的編程進行了優化,使用Go編譯的程序可以媲美C或C++代碼的速度,而且更加安全、支持並行進程。
Go語言的語法接近C語言,但是對於變量的聲明是不同的,其他語法不同之處是For循環和if判斷語句不需要用小括號括起來。Go語言支持垃圾回收功能。
與C++相比,Go語言並不包括如異常處理、繼承、泛型、斷言、虛函數等功能,但增加了slice型、並發、管道、垃圾回收、接口(interface)等特性的語言級支持。
當前有兩個Go語言的編譯器的分支。官方編譯器gc和gccgo。官方編譯器支持跨平台編譯(但
不支持CGO)
go還可以嵌入C代碼,但是不可以嵌入C++代碼,當然也可以通過某些方式調用C++ API(如SWIG),本文主要講CGO。怎么嵌入C或者調用動態庫就簡單略過了,主要注意下:
- 可以用注釋符
//和/**/包圍C代碼 - import “C” 和包含C代碼之間是沒有空行的
- 動態庫的導入和編譯選項通過LDFLAGS、CFLAGS/CXXFLAGS來設置
- 還可以用pkg-config
#cgo pkg-config : xxxxname - 編譯宏定義指定
#cgo CFLAGS: -DNDEBUG -DXXXX=2
今天先看看go和c之間的類型轉換:
char --> C.char --> byte signed char --> C.schar --> int8 unsigned char --> C.uchar --> uint8 short int --> C.short --> int16 short unsigned int --> C.ushort --> uint16 int --> C.int --> int unsigned int --> C.uint --> uint32 long int --> C.long --> int32 or int64 long unsigned int --> C.ulong --> uint32 or uint64 long long int --> C.longlong --> int64 long long unsigned int --> C.ulonglong --> uint64 float --> C.float --> float32 double --> C.double --> float64 wchar_t --> C.wchar_t --> void * -> unsafe.Pointer
編程測試:
package main
/*
#include <stdio.h>
#include <stdlib.h>
char ch = 'M';
unsigned char uch = 253;
short st = 233;
int i = 257;
long lt = 11112222;
float f = 3.14;
double db = 3.15;
void * p;
char *str = "const string";
char str1[64] = "char array";
void printI(void *i)
{
printf("print i = %d\n", (*(int *)i));
}
struct ImgInfo {
char *imgPath;
int format;
unsigned int width;
unsigned int height;
};
void printStruct(struct ImgInfo *imgInfo)
{
if(!imgInfo) {
fprintf(stderr, "imgInfo is null\n");
return ;
}
fprintf(stdout, "imgPath = %s\n", imgInfo->imgPath);
fprintf(stdout, "format = %d\n", imgInfo->format);
fprintf(stdout, "width = %d\n", imgInfo->width);
}
*/
import "C"
import (
"fmt"
"reflect"
"unsafe"
)
func main() {
fmt.Println("----------------Go to C---------------")
fmt.Println(C.char('Y'))
fmt.Printf("%c\n", C.char('Y'))
fmt.Println(C.uchar('C'))
fmt.Println(C.short(254))
fmt.Println(C.long(11112222))
var goi int = 2
// unsafe.Pointer --> void *
cpi := unsafe.Pointer(&goi)
C.printI(cpi)
fmt.Println("----------------C to Go---------------")
fmt.Println(C.ch)
fmt.Println(C.uch)
fmt.Println(C.st)
fmt.Println(C.i)
fmt.Println(C.lt)
f := float32(C.f)
fmt.Println(reflect.TypeOf(f))
fmt.Println(C.f)
db := float64(C.db)
fmt.Println(reflect.TypeOf(db))
fmt.Println(C.db)
// 區別常量字符串和char數組,轉換成Go類型不一樣
str := C.GoString(C.str)
fmt.Println(str)
fmt.Println(reflect.TypeOf(C.str1))
var charray []byte
for i := range C.str1 {
if C.str1[i] != 0 {
charray = append(charray, byte(C.str1[i]))
}
}
fmt.Println(charray)
fmt.Println(string(charray))
for i := 0; i < 10; i++ {
imgInfo := C.struct_ImgInfo{imgPath: C.CString("../images/xx.jpg"), format: 0, width: 500, height: 400}
defer C.free(unsafe.Pointer(imgInfo.imgPath))
C.printStruct(&imgInfo)
}
fmt.Println("----------------C Print----------------")
}
輸出結果:
----------------Go to C--------------- 89 Y 67 254 11112222 ----------------C to Go--------------- 77 253 233 257 11112222 float32 3.14 float64 3.15 const string [64]main._Ctype_char [99 104 97 114 32 97 114 114 97 121] char array ----------------C Print---------------- print i = 2 imgPath = ../images/xx.jpg format = 0 width = 500 imgPath = ../images/xx.jpg format = 0 width = 500 imgPath = ../images/xx.jpg format = 0 width = 500 imgPath = ../images/xx.jpg format = 0 width = 500
