簡體   English   中英

在 Go 程序中使用 cgo 共享庫

[英]Using a cgo shared library in a Go program

試圖測試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

在此處輸入圖像描述

您不能在 Go 程序中使用 cgo 共享庫,因為在同一進程中不能有多個 Go 運行時。

嘗試這樣做會給出錯誤:

# command-line-arguments
cgo-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?})
        /usr/local/go/src/runtime/panic.go:992 +0x71 fp=0x1c00004a960 sp=0x1c00004a930 pc=0x402f6d1
runtime: unexpected return pc for runtime.sigpanic called from 0x43fd5e2
stack: frame={sp:0x1c00004a960, fp:0x1c00004a9b0} stack=[0x1c00004a000,0x1c00004b000)
....
0x000001c00004aaa0:  0x0000000000000000  0x0000000000000000 
runtime.sigpanic()
        /usr/local/go/src/runtime/signal_unix.go:781 +0x3a9 fp=0x1c00004a9b0 sp=0x1c00004a960 pc=0x4043449
exit status 2

要從 go 調用 c 代碼,有 3 種可能的方法:

  1. 內聯編碼,如:
package main

//#include  <stdio.h>
//int Add(int a, int b){
//    printf("Welcome from external C function\n");
//    return a + b;
//}
import "C"
import "fmt"

func main() {
    fmt.Println(C.Add(5, 2))
}
  1. Static 鏈接,您同時擁有.c.h文件,如:
// lib.c
#include  <stdio.h>
int Add(int a, int b){
    printf("Welcome from external C function\n");
    return a + b;
}

// libadd.h
int Add(int, int);

go 文件為:

// main.go
package main

// #include "libadd.h"
import "C"
import "fmt"

func main() {
    x := C.Add(1, 2)
    fmt.Println(x)

}

我們必須將文件運行為go run. or go run github.io/xxx // go run main.go will not work as it will consider main.go only, and not consider the C file

  1. Dynamic linking, where you compile the above c file as clang -shared -fpic -Wall -g lib.c -o libadd.so and have the go file as:
// main.go
package main

//#cgo CFLAGS: -g -Wall
//#cgo LDFLAGS: -L. -ladd
//#include "libadd.h"
import "C"
import "fmt"

func main() {
    x := C.Add(1, 2)
    fmt.Println(x)
}

這里可以使用go run main.go因為庫是通過硬代碼連接的,為了分發二進制文件,共享庫loadadd.so需要與相同的二進制文件分發並存在於同一文件夾中。

我為每個案例上傳了單獨的文件夾 [這里][1]

獎金要使用 c 程序調用 go 中生成的共享庫,我們可以使用以下代碼:

// main.c
#include <stdio.h>
#include "libadd.h" // calling C file
#include "libgo.h" // calling shared library generated by GO

int main()
{
    HelloWorld();
    int x = Add(1, 2);
    printf("%d",x);
    return 0;
}

將文件編譯為:``bash clang -o main -L。 -ladd -lgo main.c // -ladd => -l(庫)是 libadd



  [1]: https://github.com/hajsf/tutorial/tree/master/ffi

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM