NotePublic/Software/Development/Language/Go/Package/CGO/CGO_的基本使用.md

2.7 KiB
Raw Blame History

CGO 的基本使用

Go 调用 C

内联编码

package main

/*
#include <stdio.h>
int test() {
    return 2016;
}
*/
import "C"

import "fmt"

func main() {
    fmt.Println(C.test())
}

编译命令如下:

CGO_ENABLED=1 CC=gcc go build

静态链接

C 代码写在 .c 和 .h 独立文件中,与 Go 代码共同编译。

/**
 * @file: demo.h
 */
#ifndef DEMO_H
#define DEMO_H

#include <stdint.h>

__attribute__ ((visibility("default"))) extern int32_t test003_init(int32_t i);

#endif // DEMO_H
/**
 * @file: demo.c
 */
#include "demo.h"

int32_t test003_init(int32_t i) {
    return i*i;
}

main.go 如下:

package main

/*
#cgo CFLAGS : -I./

#include "demo.h"
*/
import "C"

import "fmt"

func main() {
    i := C.test003_init(C.int(3))
    fmt.Println(i)
    fmt.Println("Hi")
}

编译命令如下:

CGO_ENABLED=1 CC=gcc go build

动态链接

C 代码写在 .c 和 .h 独立文件中,与 Go 代码分开编译。

/**
 * @file: demo.h
 */
#ifndef DEMO_H
#define DEMO_H

#include <stdint.h>

__attribute__ ((visibility("default"))) extern int32_t test003_init(int32_t i);

#endif // DEMO_H
/**
 * @file: demo.c
 */
#include "demo.h"

int32_t test003_init(int32_t i) {
    return i*i;
}

先将 C 代码编译成共享库,编译命令如下:

gcc -shared -o libdemo.so demo.c

main.go 如下:

package main

/*
#cgo CFLAGS : -I./
#cgo LDFLAGS: -L./ -ldemo

#include "demo.h"
*/
import "C"

import "fmt"

func main() {
    i := C.test003_init(C.int(3))
    fmt.Println(i)
    fmt.Println("Hi")
}

再编译 Go 代码:

CGO_ENABLED=1 CC=gcc go build

CGO 中的类型

基础类型

C.char
C.scharsigned char
C.ucharunsigned char
C.short
C.ushortunsigned short
C.int
C.uintunsigned int
C.long
C.ulongunsigned long
C.longlonglong long
C.ulonglongunsigned long long
C.float
C.double

nil <-> NULL

Go string 转 C string

func C.CString(goString string) *C.char

转换为 C string 会分配一个内存,因此需要释放,文档中示例如下

// #include <stdlib.h>
import "C"
import "unsafe"
...
    var cmsg *C.char = C.CString("hi")
    defer C.free(unsafe.Pointer(cmsg))
    // do something with the C string

C string 转 Go string

func C.GoString(cString *C.char) string
func C.GoStringN(cString *C.char, length C.int) string

C 调用 Go

参考 Build and Use Go Packages as C Libraries

注意事项

  1. Go 调用 C 时CGO 的注释和 import “C” 之间不能有空行否则出现“could not determine kind of name for C.xxxxx” 等莫名奇妙的错误。