Como executar o código C no código Go

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 envpara verificar se a ferramenta cgo está habilitada.

CGO_ENABLED=1Indica que a ferramenta cgo está disponível, quando definida como 0, a ferramenta está indisponível.

Então eu posso criar um CinGo.gonovo 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:

Acho que você gosta

Origin juejin.im/post/7077843585088897037
Recomendado
Clasificación