Il y a donc un tas de choses sur le groupe qui suggèrent que vous pouvez le faire en cours (mais pas dans la documentation cgo):
package bridge
import "fmt"
// #cgo CFLAGS: -I/Users/doug/projects/c/go-bridge/include
// #cgo LDFLAGS: /Users/doug/projects/c/go-bridge/build/libgb.a
// #include <junk.h>
import "C"
func Run() {
fmt.Printf("Invoking c library...\n")
C.x(10)
fmt.Printf("Done\n")
}
Cependant, cela ne semble pas fonctionner:
/var/folders/.../bridge.a(bridge.cgo2.o)(__TEXT/__text): x: not defined
Cela semble fonctionner correctement en utilisant une bibliothèque dynamique et en inspectant les fichiers générés, elle contient en fait le symbole "x":
/var/folders/rg/hj4s3qlj3sz1d1b5p50ws0vc0000gn/T/go-build442792776/bridge/_obj/_cgo_.o:
0000000100001048 S _NXArgc
0000000100001050 S _NXArgv
0000000100001060 S ___progname
0000000100000dc0 T __cgo_2d7eefe3d6d4_Cfunc_x
0000000100000da0 T __cgo_allocate
0000000100000db0 T __cgo_panic
0000000100000000 T __mh_execute_header
0000000100000d90 T _crosscall2
0000000100001058 S _environ
U _exit
0000000100000d80 T _main
U _puts
0000000100001000 s _pvars
0000000100000de0 T _x <------- Exists
U dyld_stub_binder
0000000100000d40 T start
mais n'est évidemment qu'un marqueur dans bridge.cgo2.o:
/var/folders/rg/hj4s3qlj3sz1d1b5p50ws0vc0000gn/T/go-build442792776/bridge.a(bridge.cgo2.o):
0000000000000368 s EH_frame0
0000000000000000 T __cgo_2d7eefe3d6d4_Cfunc_x
0000000000000380 S __cgo_2d7eefe3d6d4_Cfunc_x.eh
U _x
Qu'est-ce que je fais mal?
Pour ref, l'en-tête c:
int x(int y);
Et le code:
#include <junk.h>
#include <stdio.h>
int x(int y) {
printf("Hello World\n");
return y;
}
-
Modifier:
Non, -L et -l ne fonctionnent pas non plus; il y a en fait une discussion spécifique sur le groupe google que cela (-l/blah/blah.a) ne fonctionne pas pour cgo, et la syntaxe correcte is en fait pour omettre le -l et simplement lister le .un fichier ... mais bon, si ça avait marché, je l'aurais totalement utilisé. Mais ce n'est pas le cas:
dougs-mini:go doug$ go run test.go
# bridge
ld: library not found for -l/Users/doug/projects/c/go-bridge/build/libgb.a
collect2: ld returned 1 exit status
dougs-mini:go doug$ ls -l /Users/doug/projects/c/go-bridge/build/libgb.a
-rw-r--r-- 1 doug staff 872 25 May 14:02 /Users/doug/projects/c/go-bridge/build/libgb.a
version détaillée:
dougs-mini:go doug$ go build -work -x test.go
WORK=/var/folders/rg/hj4s3qlj3sz1d1b5p50ws0vc0000gn/T/go-build354497708
mkdir -p $WORK/bridge/_obj/
cd /Users/doug/projects/c/go-bridge/go/src/bridge
/Users/doug/projects/go/go/pkg/tool/darwin_AMD64/cgo -objdir $WORK/bridge/_obj/ -- -I/Users/doug/projects/c/go-bridge/include -I $WORK/bridge/_obj/ bridge.go
/Users/doug/projects/go/go/pkg/tool/darwin_AMD64/6c -FVw -I $WORK/bridge/_obj/ -I /Users/doug/projects/go/go/pkg/darwin_AMD64 -o $WORK/bridge/_obj/_cgo_defun.6 -DGOOS_darwin -DGOARCH_AMD64 $WORK/bridge/_obj/_cgo_defun.c
gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -I/Users/doug/projects/c/go-bridge/include -I $WORK/bridge/_obj/ -o $WORK/bridge/_obj/_cgo_main.o -c $WORK/bridge/_obj/_cgo_main.c
gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -I/Users/doug/projects/c/go-bridge/include -I $WORK/bridge/_obj/ -o $WORK/bridge/_obj/_cgo_export.o -c $WORK/bridge/_obj/_cgo_export.c
gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -I/Users/doug/projects/c/go-bridge/include -I $WORK/bridge/_obj/ -o $WORK/bridge/_obj/bridge.cgo2.o -c $WORK/bridge/_obj/bridge.cgo2.c
gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -o $WORK/bridge/_obj/_cgo_.o $WORK/bridge/_obj/_cgo_main.o $WORK/bridge/_obj/_cgo_export.o $WORK/bridge/_obj/bridge.cgo2.o -l/Users/doug/projects/c/go-bridge/build/libgb.a
# bridge
ld: library not found for -l/Users/doug/projects/c/go-bridge/build/libgb.a
collect2: ld returned 1 exit status
Il convient de noter que l'échec lorsque vous essayez de créer un lien comme celui-ci (en utilisant -l) est typique de l'échec de la liaison gcc parce que vous essayez de combiner un ensemble de fichiers objets.
c'est à dire. Cette:
gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -o ... -l/path/libgb.a
Ne compilera jamais sous gcc; vous devez lier une bibliothèque statique comme celle-ci:
gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -o ... /path/libgb.a
c'est à dire. Ce n'est absolument pas que je manque un -l ou -L.
Il s'avère que mon code est parfait à 100%; c'était une copie de Go 1.0; sous go 1.1 cela fonctionne. Sous go 1.0, ce n'est pas le cas.
(C'est un peu boiteux de répondre à ma propre question, je sais; mais les réponses 'use -L -l ci-dessous ne sont pas correctes non plus; cela n'a rien à voir avec cela).
Un exemple de solution de travail est disponible sur github ici pour quiconque trouvera cette question plus tard:
https://github.com/shadowmint/go-static-linking
bref ça ressemble à:
CGO_ENABLED=0 go build -a -installsuffix cgo -ldflags '-s' src/myapp/myapp.go
voir aussi: https://github.com/golang/go/issues/9344
Il vous suffit de créer un lien avec -Ldirectory -lgb.
$ cat >toto.c
int x( int y ) { return y+1; }
$ cat >toto.h
int x(int);
$ gcc -O2 -c toto.c
$ ar q libgb.a toto.o
$ cat >test.go
package main
import "fmt"
// #cgo CFLAGS: -I.
// #cgo LDFLAGS: -L. -lgb
// #include <toto.h>
import "C"
func main() {
fmt.Printf("Invoking c library...\n")
fmt.Println("Done ", C.x(10) )
}
$ go build test.go
$ ./test
Invoking c library...
Done 11
Un Makefile simple pour lier le code Go à une bibliothèque statique dynamique o:
static:
gcc -c gb.c
ar -rcs libgb.a gb.o
go build -ldflags "-linkmode external -extldflags -static" bridge.go
dynamic:
gcc -shared -o libgb.so gb.c
go build bridge.go
Directives dans bridge.go:
/*
#cgo CFLAGS: -I.
#cgo LDFLAGS: -L. -lgb
#include "gb.h"
*/
import "C"
...
Essayer:
// #cgo LDFLAGS: -l/Users/doug/projects/c/go-bridge/build/libgb.a
Vous avez manqué le -l
dans la directive LDFLAGS.