Oferta chega, cavar amigos para pegar! Estou participando do Evento Check-In de Recrutamento da Primavera de 2022, clique para ver os detalhes do evento .
prefácio
Nos artigos anteriores da série Go, aprendemos que a linguagem Go nasceu da linguagem C, o que significa que, em alguns detalhes de nível inferior, podemos usar a linguagem C para implementar e, em seguida, chamar o código C relevante por meio de Go. Na verdade, esse recurso é realizado chamando diretamente C na JVM do Java e no interpretador do Python.
Neste artigo, vamos aprender como executar programas C na linguagem Go.
Escreva programas C diretamente no código Go
A linguagem Go usa o ataque cgo para identificar a linguagem C no código. Podemos usar o comando go env
para verificar se a ferramenta cgo está habilitada.
CGO_ENABLED=1
Indica que a ferramenta cgo está disponível, quando definida como 0, a ferramenta está indisponível.
Então eu posso criar um CinGo.go
novo programa e escrever o código da linguagem c nos comentários. Em seguida, importe o pacote c fornecido pelo import "C"
Go. Depois de ver a importação deste pacote, a linguagem Go sabe como processar o conteúdo nos comentários.
Aqui nós escrevemos a callC()
função , e então a chamamos na linguagem Go:
package main
// #include <stdio.h>
// void callC() {
// printf("Hello World from C!\n");
// }
import "C"
import "fmt"
func main() {
fmt.Println("让我们学习 Go 语句调用 C 程序")
C.callC()
fmt.Println("调用 C 程序结束")
}
复制代码
Resultados do:
$ go run CinGo.go
让我们学习 Go 语句调用 C 程序
Hello World from C!
调用 C 程序结束
复制代码
No entanto, o código C e o código da linguagem Go dessa maneira estão no mesmo arquivo, portanto, obviamente, você pode descobrir que o acoplamento de código dessa maneira é muito alto e é adequado apenas para projetos simples e únicos.
Uma abordagem mais razoável seria separar o código C em um arquivo.
Go chama arquivos C diretamente
Então, se um código de arquivo C empacotado foi escrito, como a linguagem Go pode chamá-lo?
Neste ponto, precisamos escrever o código C diretamente, porque o código Go não pode reescrever ou modificar o arquivo de código C.
Escreva o arquivo de
Em nosso projeto Go local, criamos hello.h
um arquivo de cabeçalho com o seguinte código:
#ifndef HELLO_H
#define HELLO_H
int sayHello(const char *name, char *out);
void printMessage(char *message);
void cHello();
int add(int a, int b);
#endif
复制代码
Escrever arquivos
Em seguida, escreva o hello.c
arquivo da seguinte forma:
#include "hello.h"
#include <stdio.h>
int sayHello(const char *name, char *out) {
int n;
n = sprintf(out, "Hello, My name is %s!", name);
return n;
}
void cHello() {
printf("Hello from C!\n");
}
void printMessage(char* message) {
printf("从 Go 语言接收的信息: %s\n", message);
}
int add(int a, int b) {
return a + b;
}
复制代码
Escreva um bom código
Finalmente, escreva nossa main.go
linguagem :
- Precisamos preencher nosso caminho GOPath, no parâmetro CFLAGS
#cgo CFLAGS: -I /Users/yuzhou_1su/go/src/CinGo
. - Em seguida, preencha LSFLAGS com nosso arquivo de link local compilado em C
#cgo LDFLAGS: /Users/yuzhou_1su/go/src/CinGo/hello.a
:
package main
// #cgo CFLAGS: -I /Users/yuzhou_1su/go/src/CinGo
// #cgo LDFLAGS: /Users/yuzhou_1su/go/src/CinGo/hello.a
// #include <stdlib.h>
// #include <hello.h>
import "C"
import (
"fmt"
"unsafe"
)
func main() {
C.cHello()
a := C.int(1024)
b := C.int(2022)
result := C.add(a, b)
fmt.Println("Reuslt is:", result)
goMessage := C.CString("This is Go")
defer C.free(unsafe.Pointer(goMessage))
C.printMessage(goMessage)
}
复制代码
A estrutura final do código é a seguinte :
Então, primeiro compilamos o código c:
$ gcc -c *.c
$ /usr/bin/ar rs hello.a *.o
ar: creating archive hello.a
$ rm hello.o
复制代码
Em seguida, execute o código Go e o resultado é o seguinte:
$ go run main.go
Hello from C!
Reuslt is: 3046
从 Go 语言接收的信息: This is Go
复制代码
Resumir
No processo de escrever os pequenos casos acima, você encontrou muitos pequenos problemas, como falta de espaço entre o código C e a import "c"
instrução . Muitas vezes há problemas como não ser capaz de encontrar funções C.
Em geral, esse uso avançado ainda não é necessário para o desenvolvimento diário do Go, o que significa que não precisamos muito do cgo em nosso processo de programação usual e, na maioria dos casos, tentamos implementá-lo na linguagem Go. Se você realmente precisa usar a linguagem C, é melhor ler a documentação do cgo para evitar erros.
Inspirado por:
- Chamando código C de go | Karthik Karanth
- pkg.go.dev/cmd/cgo
- Proficiente na linguagem Go