如何使用cgo静态链接go中的c库?

如何使用cgo静态链接go中的c库?,go,cgo,Go,Cgo,因此,团队中有很多东西建议您可以在go中执行此操作(尽管cgo文档中没有): 使用动态库时,这似乎可以正常工作,并且检查生成的文件时,其中实际上有符号“x”: /var/folders/rg/hj4s3qlj3sz1d1b5p50ws0vc0000gn/T/go-build442792776/bridge/_obj/_cgo_.o: 0000000100001048 S _NXArgc 0000000100001050 S _NXArgv 0000000100001060 S ___prog

因此,团队中有很多东西建议您可以在go中执行此操作(尽管cgo文档中没有):

使用动态库时,这似乎可以正常工作,并且检查生成的文件时,其中实际上有符号“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
我做错了什么

对于ref,c标题:

int x(int y);
和代码:

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

int x(int y) {
  printf("Hello World\n");
  return y;
}
详细版本:

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
值得注意的是,尝试这样链接(使用-l)时的失败是gcc无法链接的典型情况,因为您试图组合一组对象文件

即:

gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -o ... -l/path/libgb.a
永远不会在gcc下编译;必须像这样链接静态库:

gcc -I . -g -O2 -fPIC -m64 -pthread -fno-common -o ... /path/libgb.a
也就是说,我绝对没有错过a-l或-l。

试试:

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

您错过了LDFLAGS指令中的
-l

您只需链接-lddirectory-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
$cat>toto.c
intx(inty){返回y+1;}
$cat>toto.h
int x(int);
$gcc-O2-c总计
$ar q libgb.a toto.o
$cat>test.go
包干管
输入“fmt”
//#cgo CFLAGS:-I。
//#cgo LDFLAGS:-L.-lgb
//#包括
输入“C”
func main(){
fmt.Printf(“调用c库…\n”)
fmt.Println(“完成”,C.x(10))
}
$go构建测试。go
美元/测试
正在调用c库。。。
完成11

结果是我的代码100%没有问题;它是Go 1.0的副本;在go 1.1下,这是可行的。 在Go1.0下,它不会

(我知道,回答我自己的问题有点站不住脚;但下面的“使用-L-L答案”也不正确;这与此无关)

github上提供了一个可行的解决方案示例,供以后发现此问题的人参考:

简言之,这看起来像:

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

将Go代码链接到动态静态库的简单Makefile:

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
bridge.go中的指令:

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

你是不是在LDFLAGS:之后缺少了一个
-L
?该死的,我希望这只是一个输入错误,除此之外,我不明白为什么它不起作用。你不是同时需要-L/Users/doug/projects/c/go bridge/build/和-lgb吗?(第一个属于LDFLAGS,第二个通常放在LDLIBS中)。@Victor这是cgo找到要链接的正确文件所必需的“元数据”,并在
-L下调用该文件。
它将改为选中
/usr/lib/
$ 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
CGO_ENABLED=0 go build -a -installsuffix cgo -ldflags '-s' src/myapp/myapp.go
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
/*
#cgo CFLAGS: -I.
#cgo LDFLAGS: -L. -lgb
#include "gb.h"
*/
import "C"
...