Zoeken…


Cgo: Eerste stappen tutorial

Enkele voorbeelden om de workflow van het gebruik van Go C-bindingen te begrijpen

Wat

In Go kunt u C-programma's en -functies oproepen met behulp van cgo . Op deze manier kunt u eenvoudig C-bindingen maken met andere toepassingen of bibliotheken die C API bieden.

Hoe

Het enige wat u hoeft te doen is om een import "C" toe te voegen aan het begin van uw Go-programma, net nadat u uw C-programma hebt toegevoegd:

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

Met het vorige voorbeeld kunt u het stdio pakket in Go gebruiken.

Als u een app moet gebruiken die zich in dezelfde map bevindt, gebruikt u dezelfde syntaxis als in C (met de " plaats van <> )

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

BELANGRIJK : laat geen nieuwe regel tussen de include en de import "C" -instructies of u krijgt dit soort fouten bij het bouwen:

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

Het voorbeeld

In deze map vindt u een voorbeeld van C-bindingen. We hebben twee zeer eenvoudige C "bibliotheken" genaamd hello.c :

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

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

Dat drukt gewoon "hallo wereld" af in de console en sum.c

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

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

... waarvoor 2 argumenten nodig zijn en de som wordt geretourneerd (niet afdrukken).

We hebben een main.go programma dat gebruik zal maken van deze twee bestanden. Eerst importeren we ze zoals eerder vermeld:

//main.go
package main

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

Hallo Wereld!

Nu zijn we klaar om de C-programma's in onze Go-app te gebruiken. Laten we eerst het Hello-programma proberen:

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

Voer nu het main.go-programma uit met behulp van go run main.go om het C-programma af te drukken: "Hallo wereld!". Goed gedaan!

Som van int

Laten we het een beetje complexer maken door een functie toe te voegen die de twee argumenten samenvat.

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

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

En we noemen het vanuit onze vorige 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
}

Bekijk de functie "makeSum". Het ontvangt twee int parameters die eerst moeten worden geconverteerd naar C int met behulp van de C.int functie. Ook zal de terugkeer van de oproep ons een C int en een fout geven in het geval er iets mis is gegaan. We moeten C-respons op een Go's int uitbrengen met int() .

Probeer onze go-app uit te voeren met go run main.go

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

Een binair getal genereren

Als je een go-build probeert, kun je meerdere definitiefouten krijgen.

$ 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

De kunst is om direct naar het hoofdbestand te verwijzen wanneer je go build :

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

Vergeet niet dat u een naam kunt go build -o my_c_binding main.go voor het binaire bestand met behulp van -o flag go build -o my_c_binding main.go

Ik hoop dat je deze tutorial leuk vond.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow