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.