Ricerca…


Cgo: Primi passi tutorial

Alcuni esempi per capire il flusso di lavoro dell'utilizzo di Go C Bindings

Che cosa

In Go puoi chiamare programmi e funzioni C usando cgo . In questo modo è possibile creare facilmente associazioni C ad altre applicazioni o librerie che forniscono API C.

Come

Tutto quello che devi fare è aggiungere una import "C" all'inizio del tuo programma Go subito dopo aver incluso il tuo programma C:

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

Con l'esempio precedente puoi usare il pacchetto stdio in Go.

Se hai bisogno di usare un'app che si trova nella tua stessa cartella, usi la stessa sintassi che in C (con " invece di <> )

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

IMPORTANTE : non lasciare una nuova riga tra le istruzioni di include e di import "C" o si otterrà questo tipo di errori durante la compilazione:

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

L'esempio

In questa cartella puoi trovare un esempio di associazioni C. Abbiamo due "librerie" C molto semplici chiamate hello.c :

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

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

Questo semplicemente stampa "ciao mondo" nella console e sum.c

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

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

... che accetta 2 argomenti e restituisce la sua somma (non stamparla).

Abbiamo un programma main.go che farà uso di questi due file. Per prima cosa li importiamo come abbiamo detto prima:

//main.go
package main

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

Ciao mondo!

Ora siamo pronti per utilizzare i programmi C nella nostra app Go. Proviamo prima il programma Hello:

//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
}

Ora esegui il programma main.go usando go run main.go per ottenere la stampa del programma C: "Hello world!". Molto bene!

Somma di ints

Facciamo un po 'più complicato aggiungendo una funzione che riassume i suoi due argomenti.

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

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

E lo chiameremo dalla nostra precedente app Go.

//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
}

Dai un'occhiata alla funzione "makeSum". Riceve due parametri int che devono essere convertiti in C int prima usando la funzione C.int . Inoltre, il ritorno della chiamata ci darà un C int e un errore nel caso qualcosa sia andato storto. Abbiamo bisogno di lanciare la risposta C a int di Go utilizzando int() .

Prova a eseguire la nostra app di go run main.go utilizzando go run main.go

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

Generare un binario

Se provi a fare una build potresti ottenere più errori di definizione.

$ 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

Il trucco è fare riferimento al file principale direttamente quando si usa go build :

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

Ricorda che puoi fornire un nome al file binario usando -o flag go build -o my_c_binding main.go

Spero che questo tutorial ti sia piaciuto.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow