수색…


Cgo : 첫 단계 튜토리얼

Go C Bindings 사용의 워크 플로를 이해하는 몇 가지 예제

Go에서는 cgo를 사용하여 C 프로그램 및 함수를 호출 할 수 있습니다. 이렇게하면 C API를 제공하는 다른 응용 프로그램이나 라이브러리에 대한 C 바인딩을 쉽게 만들 수 있습니다.

방법

C 프로그램을 포함시킨 직후 Go 프로그램 시작 부분에 import "C" 를 추가하기 만하면 됩니다.

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

이전 예에서 Go에서 stdio 패키지를 사용할 수 있습니다.

당신이 당신의 동일한 폴더에 응용 프로그램을 사용해야하는 경우, 당신은 C보다 같은 구문을 사용합니다 (로 " 대신 <> )

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

IMPORTANT : includeimport "C" 문장 사이에 개행 문자를 남기지 마십시오. 그렇지 않으면 빌드시에 이런 유형의 에러가 발생합니다 :

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

예제

이 폴더에서 C 바인딩의 예를 찾을 수 있습니다. hello.c 라는 매우 간단한 두 개의 "라이브러리"가 있습니다.

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

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

간단히 콘솔과 sum.c 에 "hello world"를 출력합니다.

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

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

... 2 개의 인수를 취하고 그 합을 반환합니다 (인쇄하지 않음).

우리는이 두 파일을 사용할 main.go 프로그램을 가지고 있습니다. 먼저 앞서 언급 한대로 가져옵니다.

//main.go
package main

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

안녕하세요!

이제 Go 앱에서 C 프로그램을 사용할 준비가되었습니다. 먼저 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
}

지금 사용 main.go 프로그램 실행 go run main.go C 프로그램의 인쇄를 얻을 : "안녕하세요 세상을". 잘 했어!

정수의 합

두 개의 인수를 합한 함수를 추가하여 좀 더 복잡하게 만듭니다.

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

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

그리고 이전 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
}

"makeSum"기능을 살펴보십시오. C.int 함수를 사용하여 C int 로 변환해야하는 두 개의 int 매개 변수를받습니다. 또한, 호출의 반환은 우리에게 C int 주고 오류가 발생했을 때 잘못되었다. int() 사용하여 Go의 int에 C 응답을 캐스팅해야합니다.

go run main.go 를 사용하여 go run main.gogo run main.go

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

바이너리 생성하기

go 빌드를 시도하면 여러 정의 오류가 발생할 수 있습니다.

$ 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

트릭은 go build 사용할 때 주 파일을 직접 참조하는 go build .

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

-o 플래그를 사용하여 이진 파일에 이름을 제공 할 수 있다는 것을 기억하십시오. go build -o my_c_binding main.go

나는 당신이이 튜토리얼을 즐겼기를 바랍니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow