style - Usar el código Go en un proyecto C existente
seo image alt tag example (1)
Desde que salió Go 1.5, comencé a echar un vistazo a cómo podría integrarlo en un proyecto mío existente.
La base de código del proyecto está escrita completamente en C para acceso de bajo nivel al hardware y otras cosas divertidas. Sin embargo, algunas de las cosas de nivel superior son tediosas, y me gustaría comenzar a escribirlas en un lenguaje de nivel superior (Ir)
¿Hay alguna forma de que pueda llamar el código Go de un programa C? Instalé Go 1.5, que agregó -buildmode=c-archive
( https://golang.org/s/execmodes ) que estoy tratando de poner en funcionamiento.
Sin embargo, parece que no puedo obtener Go para generar los archivos de cabecera apropiados para permitir que mi proyecto se compile realmente. Cuando genero el archivo, veo la función en los símbolos exportados (usando objdump), pero sin los archivos de cabecera para incluir gcc se queja de que la función no existe (como se esperaba)
Soy bastante nuevo en Go, sin embargo, me encanta el lenguaje y me gustaría utilizarlo. ¿Hay alguna forma idiomática ("idiomático" se usa mucho en el mundo de Go Veo ...) para hacer que esto juegue muy bien el uno con el otro?
El motivo por el que hice esta pregunta y mencioné específicamente Go 1.5 es que, de acuerdo con este documento, https://docs.google.com/document/d/1nr-TQHw_er6GOQRsF6T43GGhFDelrAP0NqSS_00RgZQ/edit?pli=1#heading=h.1gw5ytjfcoke Go 1.5 agregado soporte para programas que no son Go para llamar código Go. Específicamente, mencionado en la sección "Ir código vinculado a, y llamado desde, un programa que no es Go"
Para crear un archivo invocable desde C, deberá marcarlos como símbolos CGo exportados.
Por ejemplo, si creo un archivo foo.go
con los siguientes contenidos:
package main
import (
"C"
"fmt"
)
//export PrintInt
func PrintInt(x int) {
fmt.Println(x)
}
func main() {}
Las cosas importantes a tener en cuenta son:
- El paquete necesita ser llamado
main
- Necesita tener una función
main
, aunque puede estar vacía. - Necesita importar el paquete
C
- Necesita
//export
comentarios especiales para marcar las funciones que desea invocar desde C.
Puedo compilarlo como una biblioteca estática invocable en C con el siguiente comando:
go build -buildmode=c-archive foo.go
Los resultados serán un archivo foo.a
y un encabezado foo.h
En el encabezado, obtenemos lo siguiente (elidir las partes irrelevantes):
...
typedef long long GoInt64;
...
typedef GoInt64 GoInt;
...
extern void PrintInt(GoInt p0);
...
Entonces eso es suficiente para llamar a la función exportada. Podemos escribir un programa C simple que lo llame así:
#include "foo.h"
int main(int argc, char **argv) {
PrintInt(42);
return 0;
}
Podemos compilarlo con un comando como:
gcc -pthread foo.c foo.a -o foo
La opción -pthread
es necesaria porque el tiempo de ejecución de Go usa subprocesos. Cuando ejecuto el ejecutable resultante, imprime 42
.