Go语言学习之CGO(转载)

  • Golang
  • 790 clicked

1. 什么场合会使用Go与C的互操作呢?

下面的地址给出这样的答案:http://tonybai.com/2012/09/26/interoperability-between-go-and-c/

  1. 提升局部代码性能时,用C替换一些Go代码。C之于Go,好比汇编之于C。
  2. 嫌Go内存GC性能不足,自己手动管理应用内存。
  3. 实现一些库的Go Wrapper。比如Oracle提供的C版本OCI,但Oracle并未提供Go版本的以及连接DB的协议细节,因此只能通过包装C OCI版本的方式以提供Go开发者使用。
  4. Go导出函数供C开发者使用(目前这种需求应该很少见)。

2. Cgo

这个不要误解,cgo不是一个package,我们只需要import "C"就好了。

2.1. Package unsafe

顺便介绍一下unsafe包。

Package unsafe contains operations that step around the type safety of Go programs.
Packages that import unsafe may be non-portable and are not protected by the Go 1 compatibility guidelines.
unsage方法包换关于避开GO程序类型安全的操作。它引入了不安全,可能无法移植并且无法保护GO建议兼容性;

  • 指针类型
    • *类型:普通指针,用于传递对象地址,不能进行指针运算。
    • unsafe.Pointer:通用指针类型,用于转换不同类型的指针,不能进行指针运算。
    • uintptr:用于指针运算,GC 不把 uintptr 当指针,uintptr 无法持有对象。uintptr 类型的目标会被回收。
    • unsafe.Pointer 可以和 普通指针 进行相互转换。
    • unsafe.Pointer 可以和 uintptr 进行相互转换。

也就是说 unsafe.Pointer 是桥梁,可以让任意类型的指针实现相互转换,也可以将任意类型的指针转换为 uintptr 进行指针运算。

3. golang调用C语言

如果编译遇到错误:
cc1.exe: sorry, unimplemented: 64-bit mode not compiled in
说明你使用的是64的golang,而你使用的32位的MinGW,所以需要下载64位的mingw并配置环境变量。

输出:
42

切记,在注释和import"C"之间不能有空行,否则报错如下

4. golang中使用c语言中的数据类型

4.1. 数值类型

在Go中可以用如下方式访问C原生的数值类型:

4.2. 指针类型

原生数值类型的指针类型可按Go语法在类型前面加上,比如var p *C.int。而void比较特殊,用Go中的unsafe.Pointer表示。任何类型的指针值都可以转换为unsafe.Pointer类型,而unsafe.Pointer类型值也可以转换为任意类型的指针值。unsafe.Pointer还可以与uintptr这个类型做相互转换。由于unsafe.Pointer的指针类型无法做算术操作,转换为uintptr后可进行算术操作。

4.3. 字符串类型

C语言中并不存在正规的字符串类型,在C中用带结尾'\0'的字符数组来表示字符串;而在Go中,string类型是原生类型,因此在两种语言互操作是势必要做字符串类型的转换。

通过C.CString函数,我们可以将Go的string类型转换为C的"字符串"类型,再传给C函数使用。就如我们在本文开篇例子中使用的那样:

4.4. 数组类型

C语言中的数组与Go语言中的数组差异较大,后者是值类型,而前者与C中的指针大部分场合都可以随意转换。目前似乎无法直接显式的在两者之间进行转型,官方文档也没有说明。但我们可以通过编写转换函数,将C的数组转换为Go的Slice(由于Go中数组是值类型,其大小是静态的,转换为Slice更为通用一些),下面是一个整型数组转换的例子:

5. 在c中调用golang代码

很遗憾,出现了错误:

修改,拆分成两个文件:

6. 参考链接

赞赏

微信赞赏支付宝赞赏

发表评论

邮箱地址不会被公开。 必填项已用*标注