Cgo:对 [C 函数] 的未定义引用

Cgo: undefined reference to [C function]

我正在 运行在 docker 容器 (golang:1.18-bullseye) 中安装一个 go 程序。

我试过 运行同时使用 go run main.gogo run .

我的代码看起来像这样,两个 header 文件都位于 CFLAGS 中给出的 Include 目录中:

/*
#cgo LDFLAGS: -Lvendor/MyCoolLibrary/1.14.2/Bin/Linux/libSDK-Linux-Shipping.so
#cgo CFLAGS: -I vendor/MyCoolLibrary/1.14.2/Include/
#include "my_cool_sdk.h"
#include "my_cool_logging.h"*/
import "C"
import (
    "fmt"
    "log"
    "os"
    "runtime"
)

func main() {
ret := C.MyCoolFunc()
}

当我 运行 此代码时,我收到此错误消息:

/usr/bin/ld: $WORK/b001/_x002.o: in function `_cgo_6bb9bcf96ac6_Cfunc_MyCoolFunc':
/tmp/go-build/cgo-gcc-prolog:110: undefined reference to `MyCoolFunc'

我该如何解决这个问题?

编辑:我将 header 更改为:

/*
#cgo LDFLAGS: -L${SRCDIR}/vendor/MyCoolLibrary/1.14.2/Bin/Linux/libSDK-Linux-Shipping.so -lSDK-Linux-Shipping
#cgo CFLAGS: -I ${SRCDIR}/vendor/MyCoolLibrary/1.14.2/Include/
#include "my_cool_sdk.h"
#include "my_cool_logging.h"*/

和运行 go build -x . 这是输出:

WORK=/tmp/go-build1175764972
mkdir -p $WORK/b001/
cd /home/helloworld
TERM='dumb' CGO_LDFLAGS='"-g" "-O2" "-L/home/helloworld/vendor/MyCoolLibrary/1.14.2/Bin/Linux/libSDK-Linux-Shipping.so" "-lSDK-Linux-Shipping"' /usr/local/go/pkg/tool/linux_amd64/cgo -objdir $WORK/b001/ -importpath go-sandbox -- -I $WORK/b001/ -g -O2 -I ./vendor/MyCoolLibrary/1.14.2/Include/ ./main.go
cd $WORK
gcc -fno-caret-diagnostics -c -x c - -o /dev/null || true
gcc -Qunused-arguments -c -x c - -o /dev/null || true
gcc -fdebug-prefix-map=a=b -c -x c - -o /dev/null || true
gcc -gno-record-gcc-switches -c -x c - -o /dev/null || true
cd $WORK/b001
TERM='dumb' gcc -I /home/helloworld -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -I /home/helloworld/vendor/MyCoolLibrary/1.14.2/Include/ -o ./_x001.o -c _cgo_export.c
TERM='dumb' gcc -I /home/helloworld -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -I /home/helloworld/vendor/MyCoolLibrary/1.14.2/Include/ -o ./_x002.o -c main.cgo2.c
TERM='dumb' gcc -I /home/helloworld -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -I /home/helloworld/vendor/MyCoolLibrary/1.14.2/Include/ -o ./_cgo_main.o -c _cgo_main.c
cd /home/helloworld
TERM='dumb' gcc -I . -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -o $WORK/b001/_cgo_.o $WORK/b001/_cgo_main.o $WORK/b001/_x001.o $WORK/b001/_x002.o -g -O2 -L/home/helloworld/vendor/MyCoolLibrary/1.14.2/Bin/Linux/libSDK-Linux-Shipping.so -lSDK-Linux-Shipping
# go-sandbox
/usr/bin/ld: cannot find -lSDK-Linux-Shipping
collect2: error: ld returned 1 exit status

我能够重现并修复这个问题。还有一些额外的问题。首先只关注 运行ning go build:

好的,go 编译器找到了头文件,但是找不到共享库。我认为您稍微修改了问题的代码,这不是问题,但是 LDFLAGS-L 的路径必须是:

  • 相对于源目录使用${SRCDIR}
  • 绝对路径
  • 完全避免这种情况并利用 pkg-config 我只是使用包含 so 文件的相对目录作为 -L.
  • 的参数

好的,除此之外,您还必须在 LDFLAGS 中提供一个 -l 参数,以便在您指向的路径中找到文件(即:libvendera.so 需要 -lvendora)。

一旦 go build 工作,您就有一个应用程序 still needs the know where so 文件到 运行(因此是一个共享库)。为此,您可能需要设置 LD_LIBRARY_PATH 并指向包含 so 文件的目录,就像您对 -L.

所做的那样