Golang呼び出しsoファイルの例

6768 ワード

ダイナミックライブラリのテスト


test_so.h
int test_so_func(int a,int b);

test_so.c
#include "test_so.h"

int test_so_func(int a,int b)
{
    return a*b;
}

soを生成する
gcc -shared ./test_so.c -o test_so.so

soファイルをGoプロジェクトディレクトリにコピー

Goプロジェクトディレクトリ


load_so.h
int do_test_so_func(int a,int b);

load_so.c
#include "load_so.h"
#include 

int do_test_so_func(int a,int b)
{
    void* handle;
    typedef int (*FPTR)(int,int);

    handle = dlopen("./test_so.so", 1);
    FPTR fptr = (FPTR)dlsym(handle, "test_so_func");

    int result = (*fptr)(a,b);
    return result;
}

test.go
package main

/*
#include "load_so.h"
#cgo LDFLAGS: -ldl
*/
import "C"
import "fmt"

func main() {
    fmt.Println("20*30=", C.do_test_so_func(20, 30))
}

Goプロジェクトディレクトリは$GOPATH/src/ディレクトリの下に置くのも正常です.
├── bin
├── pkg
└── src
    └── test
        ├── go.mod
        ├── load_so.c
        ├── load_so.h
        ├── test
        ├── test.go
        ├── test_so.c
        ├── test_so.h
        └── test_so.so

testディレクトリはGoプロジェクトで、上記で作成したすべてのソースファイルが含まれています.$GOPATH/src/test/go buildを直接使用してtestバイナリファイルをコンパイルして生成します.ここでは、実行パスに注意する必要があります.
うんてん
$ ./test
20*30= 600

に質問


1、/**/注釈のコード次の行は必ずimport“C”で、中間に空白の行があってはいけません2、import“C”は単独で1行でなければならなくて、他のライブラリと一緒に導入することができません3、誰かがコンパイルする時に間違いを報告します:
$ go build

# command-line-arguments
/tmp/go-build489385520/b001/_x002.o: In function `_cgo_49a6b71449ae_Cfunc_do_test_so_func':
/tmp/go-build/cgo-gcc-prolog:54: undefined reference to `do_test_so_func'
collect2: error: ld returned 1 exit status

これは主に実行ディレクトリの問題で、必ず$GOPATH/src/ /ディレクトリの下で、go buildで実行し、go buildの後ろにファイル名がないでください.またはgo run .で実行したり、go run testで実行したりして、testはプロジェクト名です.go run test.goは使えません.
4、この間違いを報告する人もいます.
$ go build

# test
/tmp/go-build043875804/b001/_x003.o: In function `do_test_so_func':
./load_so.c:17: undefined reference to `dlopen'
./load_so.c:18: undefined reference to `dlsym'
collect2: error: ld returned 1 exit status

test.goファイルのcgo LDFLAGS: -ldl行は削除しないでください.