Usando el proyecto Go on existing C

Tengo un progtwig completamente escrito en C que usa varios archivos de objeto (.o) en él. Todos estos archivos se empaquetan dentro de un archivo de archivo (.a) que, a su vez, se usa en tiempo de comstackción del archivo principal (.c) progtwig.

Quiero escribir un nuevo archivo para este proyecto en Go. Mi idea es escribir este archivo .go y luego crear un archivo objeto (.o) partir de él. Luego, quiero colocar este archivo de objeto dentro del archivo de archivo (.a) ya mencionado.

Básicamente, esto significa que quiero llamar a las funciones Go desde un progtwig en C. He leído esta pregunta , y mientras me mostró que lo que quiero es posible a través de GCCGO, no está claro al 100% cómo hacerlo.

Incluso con las pruebas más básicas, recibo errores durante la fase de vinculación. Más específicamente, aquí hay uno de esos ejemplos básicos:


printString.go

 package main import ( "fmt" ) func PrintString(buff string) int { fmt.Printf(buff) return 1 } 

c_caller.c

 #define _GNU_SOURCE #include  extern int PrintString(char*) __asm__ ("print.main.PrintString"); int main() { char *string_to_pass= NULL; asprintf(&string_to_pass, "This is a test."); int result= PrintString(string_to_pass); if(result) {printf("Everything went as expected!\n");} else {printf("Uh oh, something went wrong!\n");} return result; } 

Comstackndo

Para comstackr el archivo Go, utilicé este comando:

 gccgo -c printString.go -o printString.o -fgo-prefix=print -Wall -Werror -march=native 

Para comstackrlo todo, utilicé este comando:

 gccgo -o main c_caller.c printString.o -Wall -Werror -march=native 

El mensaje de retorno que estoy recibiendo es:

 /usr/lib64/libgo.so.4.0.0: undefined reference to `main.main' /usr/lib64/libgo.so.4.0.0: undefined reference to `__go_init_main' collect2: error: ld returned 1 exit status 

Lo que significa que GCCGO’s espera una función principal en el archivo Go en lugar de la función C.

Al usar las --static-libgo , --static-libgo y -Wl,-R,/path/to/libgo.so's_folder en el segundo comando se obtiene un resultado diferente:

 /usr/bin/ld: cannot find -lgo collect2: error: ld returned 1 exit status 

Lo que no tiene sentido, ya que tengo la variable de entorno LD_LIBRARY_PATH apuntando correctamente a la carpeta de libgo.so.


Me doy cuenta de que probablemente estoy haciendo algo mal aquí, pero simplemente no puedo ver qué es eso. No hay casi ejemplos de GCCGO y su interacción con C, y la única referencia que pude encontrar fue esta página , que personalmente siento que no es suficiente.

Le pido un consejo sobre este asunto y le agradezco su tiempo. 🙂

Puede que esto no sea lo que quieres, pero en Go 1.5, que llegará en agosto, podrás crear bibliotecas compatibles con C con la herramienta go. Así que con esto en tu _main.c

 #include  int main() { char *string_to_pass = NULL; if (asprintf(&string_to_pass, "This is a test.") < 0) { printf("asprintf fail"); return -1; } PrintString(string_to_pass); return 0; } 

y esto en tu main.go

 package main import "C" import "fmt" //export PrintString func PrintString(cs *C.char) { s := C.GoString(cs) fmt.Println(s) } func main() {} 

Usted puede hacer, para la biblioteca estática:

 go build -buildmode c-archive -o mygopkg.a gcc -o main _main.c mygopkg.a -lpthread 

Para la biblioteca compartida:

 go build -buildmode c-shared -o mygopkg.so LD_RUN_PATH=$(pwd) gcc -o main _main.c mygopkg.so -lpthread 

( LD_RUN_PATH está aquí para hacer que el enlazador busque la biblioteca compartida en el mismo directorio que está creando).

Ver el documento de diseño de los modos de ejecución Ir para más información.

Actualmente no hay una forma compatible de hacer lo que quieres. Go siempre necesita el soporte de su tiempo de ejecución, y el punto de entrada para eso siempre es main . AFAIK, gccgo también hace estas mismas suposiciones y no proporciona una manera de enlazar fácilmente desde otros progtwigs.

Si desea hacer esto de una manera compatible, tendrá que esperar hasta ir 1.5.5 donde se está trabajando para comstackr las bibliotecas compartidas desde el código Go.

Si realmente quiere piratear esto ahora, puede ver cómo funciona el puerto de Android usando la cadena de herramientas de gc predeterminada con -linkmode external , que renombra main en el archivo objeto y lo llama externamente.