go调用c全面解析

一、go的指针

pointer type、 uintptr和unsafe.Pointer

  • pointer type: 指针类型,有具体基础类型指针的名称,如 *int叫整型指针类型

  • uintptr: 一个无符号整数,用于存放地址。只是一个地址,没有对地址处的数据做任何类型解释,可以做运算,如:var p uintptr p+=1。当uint看即可

  • unsafe.Pointer: unsafe包中的一个类型,指向任意指针类型的指针类型,相当于C中void*。它有四钟其他类型的特殊操作:

    • 任意类型指针能转化为unsafe.Pointer
    • unsafe.Pointer能够转化为任意类型的指针
    • unsafe.Pointer可转为uintptr
    • uintp可以转为unsafe.Pointer

    因此,一个指针类型和uintptr转化要通过unsafe.Pointer,所有go中指针操作比C麻烦太多。

  • 示例1 将[]byte中两个元素转为uint16值,可以使用 encoding/binary包中的binary.LittleEndian.Uint16函数转化,这里只是为了说明指针的转化

    b := []byte{0x01, 0x02, 0x3, 0x4}
    var u16 uint16

    pb := unsafe.Pointer(&b[1]) //pb指向b第二个元素的地址,注:&b不是slice的第一元素的地址,要用&b[0],如果为数组 [4]byte{}则&b为第一个元素的地址,原因参与雨痕的go学习笔记。
    u16 = *((*uint16)(pb))      //将b的2,3元素转为一个uint16的数,小端模式0x0302,大端模式0x0203; intel和amd CPU都是小段模式
    fmt.Printf("u16:%#04x\n", u16) //0x0302
  • 示例2 通过uintptr的运算取到数据
    var u16 uint16
    var p uintptr
    b := [4]byte{0x01, 0x02, 0x3, 0x4}
    //uintptr和指针类型不能直接转换
    //p = uintptr(&b)           //cannot convert &b (type *[4]byte) to type uintptr
    //u16 = *((*uint16)(p + 2)) //cannot convert p + 2 (type uintptr) to type *uint16
    pb := unsafe.Pointer(&b)
    p = uintptr(pb)
    fmt.Printf("p:%p\n", p) //p:0xc000071f5c
    p++
    pb = unsafe.Pointer(p)
    u16 = *((*uint16)(pb))
    fmt.Printf("u16:%#04x\n", u16) //u16:0x0302

二、go中直接嵌入C代码

三、go调用windows的dll

四、go调用linux的so

五、go代码编译为dll和so

你可能感兴趣的:(go调用c全面解析)