2013-05-25 8 views
22

Quindi c'è un mucchio di roba sul gruppo che suggerisce si può fare questo a go (anche se non sulla documentazione CGO):Come si collega staticamente una libreria c all'utilizzo di 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") 
} 

Tuttavia, non sembra funzionare:

/var/folders/.../bridge.a(bridge.cgo2.o)(__TEXT/__text): x: not defined 

Questo sembra funzionare bene utilizzando una libreria dinamica, e ispezionare i file generati, in realtà ha il simbolo 'x' in là:

/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 

ma ovviamente è solo un marker in 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 

Cosa sto facendo male?

Per ref, il c intestazione:

int x(int y); 

E Codice:

#include <junk.h> 
#include <stdio.h> 

int x(int y) { 
    printf("Hello World\n"); 
    return y; 
} 

-

Edit:

No, -L e -l non lavorare sia; c'è in realtà qualche discussione specifica sul gruppo di google che questo (-l/blah/blah.a) non funziona per cgo, e la sintassi corretta è infatti per omettere il -l e basta elencare il file .a .. ma hey, se avesse funzionato, lo userei totalmente. Ma non è così:

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 

versione verbose:

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 

Vale la pena notare che il fallimento, quando si tenta di collegare in questo modo (usando -l) è tipico di gcc non riuscire a collegare perché si Stai tentando di combinare un insieme di file oggetto.

ie. Questo:

gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -o ... -l/path/libgb.a 

Non verrà mai compilato in gcc; si necessario collegare una libreria statica come questo:

gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -o ... /path/libgb.a 

es. Non è assolutamente che mi manchi un -l o -L.

+0

Vi manca un '' -l' dopo LDFLAGS: '? – Intermernet

risposta

27

Il mio codice è corretto al 100%; era una copia di Go 1.0; sotto andare 1.1 questo funziona. Sotto vai 1.0, non è così.

(è un po 'zoppicante rispondere alla mia stessa domanda, lo so, ma le risposte "uso -L -l" di seguito non sono corrette, non ha nulla a che fare con questo).

Un esempio soluzione di lavoro è su GitHub qui per tutti coloro che trovano è questa domanda successiva:

https://github.com/shadowmint/go-static-linking

insomma che assomiglia:

CGO_ENABLED=0 go build -a -installsuffix cgo -ldflags '-s' src/myapp/myapp.go 

vedi anche: https://github.com/golang/go/issues/9344

0

Prova:

// #cgo LDFLAGS: -l/Users/doug/projects/c/go-bridge/build/libgb.a 

vi siete persi la -l nella direttiva LDFLAGS.

+0

no, anche questo non funziona, vedi la mia modifica sopra. – Doug

+0

Dannazione, speravo fosse solo un errore di battitura, a parte quello non riesco a capire perché non funzionerebbe – Intermernet

+0

Non è che tu abbia bisogno di entrambi -L/Users/doug/projects/c/go-bridge/build/e -lgb? (il primo appartiene a LDFLAGS, il secondo di solito viene inserito in LDLIBS). – fuz

9

Devi solo collegarti con -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 
+0

Risposta molto utile, ha funzionato come per magia. Grazie mille! –

+0

Qual è il contenuto del commento cgo .. – Victor

1

Un Makefile semplice per collegare il codice Go a uno dinamico o libreria statica:

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 

direttive in bridge.go:

/* 
#cgo CFLAGS: -I. 
#cgo LDFLAGS: -L. -lgb 
#include "gb.h" 
*/ 
import "C" 
... 
Problemi correlati