猿问

在 Go 程序中使用 cgo 共享库

试图测试cgo,所以我写了以下内容:


//go:build lib

// +build lib


package main


import "C"

import "fmt"


//export HelloWorld

func HelloWorld() {

    fmt.Printf("hello world")

}


func main() {}


// go build -tags lib -buildmode=c-shared -o golib.a lib.go

并将其编译为:


$ go build -tags lib -buildmode=c-shared -o golib.a lib.go

尝试在另一个代码中使用生成的共享库:


//go:build app

// +build app


package main


// #cgo CFLAGS: -g -Wall

// #include <stdlib.h>

// #include "golib.h"

import "C"


func main() {

    C.HelloWorld()

}


// go run main.go

但我收到以下错误:


# command-line-arguments

Undefined symbols for architecture x86_64:

  "_HelloWorld", referenced from:

      __cgo_a844f0d618a1_Cfunc_HelloWorld in _x002.o

     (maybe you meant: __cgo_a844f0d618a1_Cfunc_HelloWorld)

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

# command-line-arguments

cgo-gcc-prolog:47:33: warning: unused variable '_cgo_a' [-Wunused-variable]

此外,我在 mac 上使用 VS 代码收到以下错误:


go list failed to return CompiledGoFiles. This may indicate failure to perform cgo processing; try building at the command line. See https://golang.org/issue/38990

在此处输入图像描述



POPMUISE
浏览 390回答 1
1回答

慕桂英3389331

你不能在 Go 程序中使用 cgo 共享库,因为你不能在同一个进程中有多个 Go 运行时。尝试这样做会给出错误:# command-line-argumentscgo-gcc-prolog:67:33: warning: unused variable '_cgo_a' [-Wunused-variable]fatal error: unexpected signal during runtime execution[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x43fd5e2]goroutine 1 [running, locked to thread]:runtime.throw({0x40a875b?, 0x1c00011b800?})&nbsp; &nbsp; &nbsp; &nbsp; /usr/local/go/src/runtime/panic.go:992 +0x71 fp=0x1c00004a960 sp=0x1c00004a930 pc=0x402f6d1runtime: unexpected return pc for runtime.sigpanic called from 0x43fd5e2stack: frame={sp:0x1c00004a960, fp:0x1c00004a9b0} stack=[0x1c00004a000,0x1c00004b000)....0x000001c00004aaa0:&nbsp; 0x0000000000000000&nbsp; 0x0000000000000000&nbsp;runtime.sigpanic()&nbsp; &nbsp; &nbsp; &nbsp; /usr/local/go/src/runtime/signal_unix.go:781 +0x3a9 fp=0x1c00004a9b0 sp=0x1c00004a960 pc=0x4043449exit status 2要从 go 调用 c 代码,有 3 种可能的方法:内联编码,如:package main//#include&nbsp; <stdio.h>//int Add(int a, int b){//&nbsp; &nbsp; printf("Welcome from external C function\n");//&nbsp; &nbsp; return a + b;//}import "C"import "fmt"func main() {&nbsp; &nbsp; fmt.Println(C.Add(5, 2))}静态链接,您同时拥有.c和.h文件,如:// lib.c#include&nbsp; <stdio.h>int Add(int a, int b){&nbsp; &nbsp; printf("Welcome from external C function\n");&nbsp; &nbsp; return a + b;}和// libadd.hint Add(int, int);go 文件是:// main.gopackage main// #include "libadd.h"import "C"import "fmt"func main() {&nbsp; &nbsp; x := C.Add(1, 2)&nbsp; &nbsp; fmt.Println(x)}我们必须将文件运行为go run .或go run github.io/xxx // go run main.go 将不起作用,因为它只会考虑 main.go,而不考虑 C 文件动态链接,您将上述c文件编译为clang -shared -fpic -Wall -g lib.c -o libadd.so并将 go 文件作为:// main.gopackage main//#cgo CFLAGS: -g -Wall//#cgo LDFLAGS: -L. -ladd//#include "libadd.h"import "C"import "fmt"func main() {&nbsp; &nbsp; x := C.Add(1, 2)&nbsp; &nbsp; fmt.Println(x)}这里你可以使用go run main.go通过硬代码连接的库,分发二进制文件,共享库loadadd.so需要与相同的二进制文件一起分发并且存在于同一个文件夹中。我在这里为每个案例上传了单独的文件夹。奖励 要使用 ac 程序在 go 中调用生成的共享库,我们可以使用以下命令:// main.c#include <stdio.h>#include "libadd.h" // calling C file#include "libgo.h" // calling shared library generated by GOint main(){&nbsp; &nbsp; HelloWorld();&nbsp; &nbsp; int x = Add(1, 2);&nbsp; &nbsp; printf("%d",x);&nbsp; &nbsp; return 0;}将文件编译为:clang -o main -L. -ladd -lgo main.c&nbsp; &nbsp;// -ladd => -l (library) is libadd
随时随地看视频慕课网APP

相关分类

Go
我要回答