基本类型

Go 字符串和切片

参考 reflectStringHeaderSliceHeader 定义

_GoString_ 预定义类型

结构体、联合和枚举类型

结构体在 C 中使用 struct <name> 来指定类型,但是在 Go 中包定义的情况下就需要使用 C.struct_<name> 来指定对应的结构体类型,或者使用 typedef 指定别名后使用。

结构体字段与 Go 关键字重名

比如 type 关键字,在 C 结构体中的 type 字段可以在 Go 中用 _type 来代替:

  1. /*
  2. struct A {
  3. int type;
  4. }
  5. import "C"
  6. func main() {
  7. var a C.struct_A
  8. print(C._type)
  9. */

联合体在 Go 中使用 C.union_<name> 来访问,并且会被转换成对应大小的字节数组。

联合体在 Go 中的操作方式

联合体在 Go 的操作方式有三种:

  • 在 C 语言中定义辅助函数
  • 通过 encoding/binary 手工解码成员(注意端序问题)
  • 通过 unsafe 包强制转换为对应类型(性能最好)
    • 对于嵌套联合体的访问复杂,建议使用 C 辅助函数处理

枚举类型使用 C.enum_<name> 来访问

数组、字符串和切片

C Go
数组 指向特定类型特定长度 的一段内存的指针 值类型,长度也是其一部分
字符串 char 类型的数组,长度由表示结尾的 NULL 字符的确定 一段长度确定的只读 byte 类型的内存,结构参考 reflect.StringHeader
切片 简化版动态数组,结构参考 reflect.SliceHeader

CGO 的 C 虚拟包中提供了一组函数用于双向转换:

// string
func C.CString(string) *C.char
func C.GoString(*C.char) string
func C.GoStringN(*C.char, C.int) string // 长度为 n 的数组

// bytes
// 通过 malloc 分配,需要手动 free
func C.CBytes([]byte) unsafe.Pointer
C.GoBytes(unsafe.Pointer, C.int) []byte

指针的转换

通过 unsafe.Pointer 可以实现不同类型指针的互相转换。

Go 禁止数值类型到指针类型的转换,但是可以通过 uintptr 类型来实现