Sök…


Ringa C-funktion från Go

Cgo möjliggör skapandet av Go-paket som kallar C-kod.
För att använda cgo skriver du normal Go-kod som importerar ett pseudopaket "C". Go-koden kan sedan hänvisa till typer som C.int , eller funktioner som C.Add .
Importen av "C" föregås omedelbart av en kommentar, den kommentaren, kallad ingressen, används som en rubrik när man sammanställer paketets C-delar.
Observera att det inte får finnas några tomma rader mellan cgo kommentaren och cgo .
Observera att import "C" inte kan grupperas med annan import i ett parentesiserat "fakturerat" importmeddelande. Du måste skriva flera importförklaringar, som:

import "C"
import "fmt"

Och det är bra stil att använda det fakturerade importmeddelandet, för annan import, som:

import "C"
import (
    "fmt"
    "math"
)

Enkelt exempel med hjälp av cgo :

package main

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

func main() {
    a := C.int(10)
    b := C.int(20)
    c := C.Add(a, b)
    fmt.Println(c) // 30
}

go build , och kör den, output:

30

För att bygga cgo paket använder du bara go build eller go install som vanligt. go tool känner igen den speciella "C" -importen och använder automatiskt cgo för dessa filer.

Tråd C och Go-kod i alla riktningar

Ringer C-kod från Go

package main

/*
// Everything in comments above the import "C" is C code and will be compiles with the GCC. 
// Make sure you have a GCC installed.

int addInC(int a, int b) {
    return a + b;
}
 */
import "C"
import "fmt"

func main() {
       a := 3
       b := 5
       
       c := C.addInC(C.int(a), C.int(b))

       fmt.Println("Add in C:", a, "+", b, "=", int(c))
}

Ringer Go-kod från C

package main

/*
static inline int multiplyInGo(int a, int b) {
    return go_multiply(a, b);
}
 */
import "C"
import (
       "fmt"
)

func main() {
       a := 3
       b := 5
       
       c := C.multiplyInGo(C.int(a), C.int(b))

       fmt.Println("multiplyInGo:", a, "*", b, "=", int(c))
}

//export go_multiply
func go_multiply(a C.int, b C.int) C.int {
       return a * b
}

Att hantera funktionspekare

package main

/*
int go_multiply(int a, int b);

typedef int (*multiply_f)(int a, int b);
multiply_f multiply;

static inline init() {
    multiply = go_multiply;
}

static inline int multiplyWithFp(int a, int b) {
    return multiply(a, b);
}
 */
import "C"
import (
       "fmt"
)

func main() {
       a := 3
       b := 5
       C.init(); // OR:
       C.multiply = C.multiply_f(go_multiply);

       c := C.multiplyWithFp(C.int(a), C.int(b))

       fmt.Println("multiplyInGo:", a, "+", b, "=", int(c))
}

//export go_multiply
func go_multiply(a C.int, b C.int) C.int {
       return a * b
}

Konvertera typer, åtkomststrukturer och pekarräkning

Från den officiella Go-dokumentationen:

// Go string to C string
// The C string is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CString(string) *C.char

// Go []byte slice to C array
// The C array is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CBytes([]byte) unsafe.Pointer

// C string to Go string
func C.GoString(*C.char) string

// C data with explicit length to Go string
func C.GoStringN(*C.char, C.int) string

// C data with explicit length to Go []byte
func C.GoBytes(unsafe.Pointer, C.int) []byte

Hur man använder det:

func go_handleData(data *C.uint8_t, length C.uint8_t) []byte {
       return C.GoBytes(unsafe.Pointer(data), C.int(length))
}

// ...

goByteSlice := []byte {1, 2, 3}
goUnsafePointer := C.CBytes(goByteSlice)
cPointer := (*C.uint8_t)(goUnsafePointer)

// ...

func getPayload(packet *C.packet_t) []byte {
       dataPtr := unsafe.Pointer(packet.data)
       // Lets assume a 2 byte header before the payload.
       payload := C.GoBytes(unsafe.Pointer(uintptr(dataPtr)+2), C.int(packet.dataLength-2))
       return payload
}


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow