Usando el código Go en un proyecto C existente

Desde que salió Go 1.5, comencé a analizar cómo podría integrarlo en uno de mis proyectos existentes.

El código base del proyecto está escrito completamente en C para acceso de bajo nivel a 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 llamar al código Go desde un progtwig en C? Instalé Go 1.5, que agregue -buildmode=c-archive ( https://golang.org/s/execmodes ) que estoy tratando de hacer funcionar.

Sin embargo, parece que no consigo que Go genere los archivos de encabezado adecuados 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 encabezado que incluyen gcc se queja de que la función no existe (como se esperaba)

Soy bastante nuevo en Go, sin embargo, me encanta el idioma y me gustaría utilizarlo. ¿Hay alguna forma idiomática (“idiomático” se usa mucho en el mundo de Go, veo …) para que esto funcione bien entre sí?

La razón por la 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.1gw5yfccc Soporte para progtwigs no-Go para llamar al código Go. Específicamente, se menciona en la sección “Código Go vinculado con, y llamado desde, un progtwig que no es Go”

Para crear un archivo que se pueda llamar desde C, deberá marcarlos como símbolos CGo exportados.
Por ejemplo, si creo un archivo foo.go con el siguiente contenido:

 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 debe ser llamado main
  • Necesitas tener una función main , aunque puede estar vacía.
  • Necesitas importar el paquete C
  • Necesita //export comentarios especiales para marcar las funciones que desea llamar desde C.

Puedo comstackrlo como una biblioteca estática que se puede llamar 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 partes irrelevantes):

 ... typedef long long GoInt64; ... typedef GoInt64 GoInt; ... extern void PrintInt(GoInt p0); ... 

Eso es suficiente para llamar a la función exportada. Podemos escribir un progtwig en C simple que lo llame así:

 #include "foo.h" int main(int argc, char **argv) { PrintInt(42); return 0; } 

Podemos comstackrlo con un comando como:

 gcc -pthread foo.c foo.a -o foo 

La opción -pthread es necesaria porque el tiempo de ejecución Go hace uso de subprocesos. Cuando ejecuto el ejecutable resultante se imprime 42 .