Intento llamar a un puntero de función C como una devolución de llamada desde una función Go, pero obtengo un error de vinculación que no entiendo.
package main /* typedef void (*int_int)(int, int); void bridge_int_int(int a, int b, int_int f){ f(a, b); } */ import "C" //export IntIntCallback func IntIntCallback(a, b C.int, cb C.int_int) { C.bridge_int_int(a, b, cb) } func main() { // Noop, required to make CGO happy: `-buildmode=c-*` requires exactly one // main package, which in turn needs a `main` function`. }el error es:
c:/mingw32/bin/../lib/gcc/i686-w64-mingw32/11.2.0/../../../../i686-w64-mingw32/bin/ld.exe: $WORK\b001\_x002.o: in function `bridge_int_int': ./test.go:6: multiple definition of `bridge_int_int'; $WORK\b001\_x001.o:/tmp/test.go:6: first defined here collect2.exe: error: ld returned 1 exit statusNo entiendo de dónde viene este problema de definición múltiple.
Problema resuelto. Ver: https://pkg.go.dev/cmd/cgo#hdr-C_references_to_Go
El uso de //exportar en un archivo impone una restricción en el preámbulo: dado que se copia en dos archivos de salida C diferentes, no debe contener ninguna definición, solo declaraciones. Si un archivo contiene tanto definiciones como declaraciones, los dos archivos de salida producirán símbolos duplicados y el enlazador fallará. Para evitar esto, las definiciones deben colocarse en preámbulos en otros archivos o en archivos fuente C.
Moviendo el siguiente código a un archivo .go separado:
/* typedef void (*int_int)(int, int); void bridge_int_int(int a, int b, int_int f){ f(a, b); } */ import "C"y cambiándolo a
/* typedef void (*int_int)(int, int); extern bridge_int_int(int a, int b, int_int f); } */ import "C" ...en el archivo original solucionado el problema