golang之cgo一---go与C基本类型转换

FreeApe · · 22641 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

  在嵌入式开发中总少不了和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
总结 

  在基本类型中,C和go之间的类型转换还是比较方便的。但是区分字符串和字符数组是不同的类型。其中有个很重要的转换:void * -> unsafe.Pointer

https://golang.org/cmd/cgo/
https://zh.wikipedia.org/wiki/Go#cite_note-6


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:FreeApe

查看原文:golang之cgo一---go与C基本类型转换

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

22641 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传