Suche…


Cgo: Erste Schritte Tutorial

Einige Beispiele, um den Arbeitsablauf bei der Verwendung von Go-C-Bindungen zu verstehen

Was

In Go können Sie mit cgo C-Programme und Funktionen aufrufen . Auf diese Weise können Sie problemlos C-Bindungen für andere Anwendungen oder Bibliotheken erstellen, die C-API bereitstellen.

Wie

Alles, was Sie tun müssen, ist, ein import "C" am Anfang Ihres Go-Programms hinzuzufügen, unmittelbar nachdem Sie Ihr C-Programm hinzugefügt haben:

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

Mit dem vorherigen Beispiel können Sie das stdio Paket in Go verwenden.

Wenn Sie eine App verwenden müssen, die sich in demselben Ordner befindet, verwenden Sie dieselbe Syntax wie in C (mit " anstelle von <> )".

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

WICHTIG : Lassen Sie keine Newline zwischen den Anweisungen include und import "C" Andernfalls erhalten Sie diese Art von Fehlern beim Build:

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

Das Beispiel

In diesem Ordner finden Sie ein Beispiel für C-Bindungen. Wir haben zwei sehr einfache "Bibliotheken" namens hello.c :

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

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

Das druckt einfach "Hallo Welt" in der Konsole und in sum.c

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

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

... das nimmt 2 Argumente und gibt die Summe zurück (nicht drucken).

Wir haben ein main.go Programm, das diese beiden Dateien verwenden wird. Zuerst importieren wir sie wie zuvor erwähnt:

//main.go
package main

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

Hallo Welt!

Jetzt können wir die C-Programme in unserer Go-App verwenden. Versuchen wir zuerst das Hello-Programm:

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

Führen Sie nun das main.go-Programm mit dem go run main.go , um den Ausdruck des C-Programms zu erhalten: "Hallo Welt!". Gut gemacht!

Summe der Beträge

Lassen Sie uns etwas komplexer machen, indem Sie eine Funktion hinzufügen, die die beiden Argumente summiert.

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

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

Und wir rufen es von unserer vorherigen Go-App an.

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

Schauen Sie sich die "makeSum" -Funktion an. Es empfängt zwei int Parameter, die zuvor mithilfe der C.int Funktion in C int C.int müssen. Die Rückgabe des Anrufs gibt uns auch ein C int und einen Fehler, falls etwas schief gelaufen ist. Wir müssen eine C-Antwort mit int() auf ein int von Go setzen.

Versuchen Sie, unsere Go-App mit go run main.go

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

Eine Binärdatei erzeugen

Wenn Sie einen go-Build versuchen, könnten Sie mehrere Definitionsfehler erhalten.

$ 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

Der Trick besteht darin, direkt auf die Hauptdatei zu verweisen, wenn Sie go build :

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

Denken Sie daran, dass Sie der Binärdatei einen Namen geben können, indem Sie das Flag -o verwenden. go build -o my_c_binding main.go

Ich hoffe, dir hat dieses Tutorial gefallen.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow