golang中调用C代码

为什么调C?
著名的开源库和性能。

  1. C代码可以写入到go文件中,要写在最前面,C代码用注释的写法,最后import C;
package main

// int add(int a, int b) {
//     return a + b;
// }
import "C"

import "fmt"

func main() {
    a := C.int(1)
    b := C.int(2)
    value := C.add(a, b)
    fmt.Printf("%v\n", value)
    fmt.Printf("%v\n", int(value))
}
  1. include头文件、动态链接库的写法:
1) 使用相对路径: #include "../header/header.h"
2) 使用库地址:
#cgo LDFLAGS: -L../../../../../shared/lib/ -lcloud_sdk_api
#cgo CFLAGS: -I../../../../../shared/inc/cloud_api/
#include "cloud_sdk_server_api.h"
3)文件放到一起:   foo.h   foo.c   main.go(里面include "foo.h"即可)
  1. 数组指针的转换
go转C的*int:
    in := []C.int{1, 2, 3, 4}
    inPointer := unsafe.Pointer(&in[0])
    inC := (*C.int)(inPointer)   // *int
C的*int转go的slice:
    outC := C.return_array_pointer(4)
    defer C.free(unsafe.Pointer(outC))

    sh := reflect.SliceHeader{uintptr(unsafe.Pointer(outC)), n, n}
    out := *(*[]C.int)(unsafe.Pointer(&sh))

func CArrayToGoArray(cArray unsafe.Pointer, size int) (goArray []int) {
    p := uintptr(cArray)
    for i :=0; i < size; i++ {
        j := *(*int)(unsafe.Pointer(p))
        goArray = append(goArray, j)
        p += unsafe.Sizeof(j)
    }
    return
}
CArrayToGoArray(unsafe.Pointer(&C.cArray[0]), 7)
  1. 访问C的结构体

C语言中的结构体类型在Go语言中的表现形式为C.struct_XXX
访问结构体 直接通过结构体变量.属性名称即可

package main
/*
#include 
struct Point {
    float x;
    float y;
};
*/
import "C"
import (
    "fmt"
)

func main()  {
    // 1.利用C的结构体类型创建结构体
    var cp C.struct_Point = C.struct_Point{6.6, 8.8}
    fmt.Println(cp)
    fmt.Printf("%T\n", cp)

    // 2.将C语言结构体转换为Go语言结构体
    type GoPoint struct {
        x float32
        y float32
    }
    var gp GoPoint
    gp.x = float32(cp.x)
    gp.y = float32(cp.y)
    fmt.Println(gp)
}
  1. 字符串
package main
/*
void copy_date(char * src) {

    int size = 0;
    char ss[20];
    size = strlen(src);
    memcpy(ss, src, size);

    printf("------------------:%s\n", ss);
}
*/
import "C"
import (
    "fmt"
)

func main()  {
    C.copy_date(C.CString("20190522"));
    // 1.C语言字符串转换Go语言字符串
    str1 := C.str
    str2 := C.GoString(str1)
    fmt.Println(str2)

    // 2.Go语言字符串转换C语言字符串
    str := "lnj"
    cs := C.CString(str)
    C.say(cs)
    // 注意: 转换后所得到的C字符串cs并不能由Go的gc所管理,我们必须手动释放cs所占用的内存
    C.free(unsafe.Pointer(cs))
}

  1. C中使用Go函数

与在Go中使用C源码相比,在C中使用Go函数的场合较少。在Go中,可以使用"export + 函数名"来导出Go函数为C所使用

  1. 编译
    可以通过设置 CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS, CGO_FFLAGS and CGO_LDFLAGS 环境变量,来设置C的编译参数。

http://bastengao.com/blog/2017/12/go-cgo-c.html
https://tonybai.com/2012/09/26/interoperability-between-go-and-c/
https://www.jianshu.com/p/90f5d0a28326
详细说明: 源码的go\src\cmd\cgo\doc.go
CGO(含编译说明): https://golang.org/cmd/cgo/

你可能感兴趣的:(golang中调用C代码)