Sök…


Cgo: Tutorials för första steg

Några exempel för att förstå arbetsflödet för att använda Go C-bindningar

Vad

I Go kan du ringa C-program och funktioner med hjälp av cgo . På så sätt kan du enkelt skapa C-bindningar till andra applikationer eller bibliotek som tillhandahåller C API.

Hur

Allt du behöver göra är att lägga till en import "C" i början av ditt Go-program precis efter att du har inkluderat ditt C-program:

//#include <stdio.h>
import "C"

Med föregående exempel kan du använda stdio paketet i Go.

Om du behöver använda en app som finns i samma mapp använder du samma syntax än i C (med " istället för <> )

//#include "hello.c"
import "C"

VIKTIGT : Lämna inte en ny linje mellan include och import "C" uttalanden, så får du den här typen av fel vid build:

# command-line-arguments
could not determine kind of name for C.Hello
could not determine kind of name for C.sum

Exemplet

I den här mappen kan du hitta ett exempel på C-bindningar. Vi har två mycket enkla C-bibliotek som heter hello.c :

//hello.c
#include <stdio.h>

void Hello(){
    printf("Hello world\n");
}

Det skriver helt enkelt ut "hejvärld" i konsolen och sum.c

//sum.c
#include <stdio.h>

int sum(int a, int b) {
    return a + b;
}

... som tar två argument och returnerar summan (skriv inte ut den).

Vi har ett main.go program som kommer att använda dessa två filer. Först importerar vi dem som vi nämnde tidigare:

//main.go
package main

/*
  #include "hello.c"
  #include "sum.c"
*/
import "C"

Hej världen!

Nu är vi redo att använda C-programmen i vår Go-app. Låt oss först prova Hello-programmet:

//main.go
package main

/*
  #include "hello.c"
  #include "sum.c"
*/
import "C"


func main() {
    //Call to void function without params
    err := Hello()
    if err != nil {
        log.Fatal(err)
    }
}

//Hello is a C binding to the Hello World "C" program. As a Go user you could
//use now the Hello function transparently without knowing that it is calling
//a C function
func Hello() error {
    _, err := C.Hello()    //We ignore first result as it is a void function
    if err != nil {
        return errors.New("error calling Hello function: " + err.Error())
    }

    return nil
}

Kör nu main.go-programmet med hjälp av go run main.go att få utskrift av C-programmet: "Hej värld!". Bra gjort!

Summan av ints

Låt oss göra det lite mer komplicerat genom att lägga till en funktion som sammanfattar sina två argument.

//sum.c
#include <stdio.h>

int sum(int a, int b) {
  return a + b;
}

Och vi kommer att ringa det från vår tidigare Go-app.

//main.go
package main

/*
#include "hello.c"
#include "sum.c"
*/
import "C"

import (
    "errors"
    "fmt"
    "log"
)

func main() {
    //Call to void function without params
    err := Hello()
    if err != nil {
        log.Fatal(err)
    }

    //Call to int function with two params
    res, err := makeSum(5, 4)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Sum of 5 + 4 is %d\n", res)
}

//Hello is a C binding to the Hello World "C" program. As a Go user you could
//use now the Hello function transparently without knowing that is calling a C
//function
func Hello() error {
    _, err := C.Hello() //We ignore first result as it is a void function
    if err != nil {
        return errors.New("error calling Hello function: " + err.Error())
    }

    return nil
}

//makeSum also is a C binding to make a sum. As before it returns a result and
//an error. Look that we had to pass the Int values to C.int values before using
//the function and cast the result back to a Go int value
func makeSum(a, b int) (int, error) {
    //Convert Go ints to C ints
    aC := C.int(a)
    bC := C.int(b)

    sum, err := C.sum(aC, bC)
    if err != nil {
        return 0, errors.New("error calling Sum function: " + err.Error())
    }

    //Convert C.int result to Go int
    res := int(sum)

    return res, nil
}

Ta en titt på "makeSum" -funktionen. Den får två int parametrar som måste konverteras till C int innan med hjälp av C.int funktionen. Dessutom kommer samtalets återkomst att ge oss en int och ett fel om något skulle gå fel. Vi måste skicka C-svar på ett Go-int med int() .

Prova att köra vår go-app genom att använda go run main.go

$ go run main.go
Hello world!
Sum of 5 + 4 is 9

Generera en binär

Om du försöker en go build kan du få flera definitionsfel.

$ go build
# github.com/sayden/c-bindings
/tmp/go-build329491076/github.com/sayden/c-bindings/_obj/hello.o: In function `Hello':
../../go/src/github.com/sayden/c-bindings/hello.c:5: multiple definition of `Hello'
/tmp/go-build329491076/github.com/sayden/c-bindings/_obj/main.cgo2.o:/home/mariocaster/go/src/github.com/sayden/c-bindings/hello.c:5: first defined here
/tmp/go-build329491076/github.com/sayden/c-bindings/_obj/sum.o: In function `sum':
../../go/src/github.com/sayden/c-bindings/sum.c:5: multiple definition of `sum`
/tmp/go-build329491076/github.com/sayden/c-bindings/_obj/main.cgo2.o:/home/mariocaster/go/src/github.com/sayden/c-bindings/sum.c:5: first defined here
collect2: error: ld returned 1 exit status

Tricket är att referera till huvudfilen direkt när du använder go build :

$ go build main.go
$ ./main
Hello world!
Sum of 5 + 4 is 9

Kom ihåg att du kan ange ett namn på den binära filen genom att använda -o flagga go build -o my_c_binding main.go

Jag hoppas att du gillade den här tutorialen.



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