LabVIEWで作った .so(shared library)を Goから呼び出す

概要

使いみちの少ない LabVIEW for linuxですが、曲がりなりにも実行ファイルも.soも作れる。 最近、勉強し始めたGo言語(以下、golang)から、LabVIEWで作成した.soを呼び出せるかどうかを試してみた。

golang (1.10)の cgoを使って、LabVIEW for linuxで作成した.soの関数を呼び出す。

テストした環境

注意

golangでは、他のOSやCPU用のクロスコンパイルができるが、今回作成に使った LabVIEW for linuxは、64bit版のため、.soファイルも Linux 64bit x86専用。 (バージョン2018あたりから、Linux用の32bit版LabVIEWはサポートされなくなっている) そのため、作成される実行ファイルも.soも64bit x86専用。 当然、LabVIEW Runtimeが入っている環境でないと動かない。 RasPiあたりでも使えるとありがたいのだが、それはできない。

ソース

LabVIEW

関数例 Add

f:id:alucky4416:20190517233940p:plain
Add.vi ダイアグラム

.soファイルのビルド設定

ビルド設定は、WindowsLabVIEWでDLLを作成する場合と同様

f:id:alucky4416:20190517234228p:plain
ビルド設定

shared libraryに組み込む関数のプロトタイプ定義

f:id:alucky4416:20190517234535p:plain
関数のプロトタイプ定義

Go側

LabVIEWで作成したshared library 中の関数を呼び出す側のサンプル。

cgoを使うといっても、cgoで直接shared libraryに含まれている関数を呼び出すのではなく、<dlfcn.h>で定義されている shared libraryを扱う関数を使って、share library中の関数を呼び出している。このため、以下のサンプルはWindowsでは使えない。Windows用DLLを扱う仕組みは別に用意されている。

golangでのサンプル

package main

/*
#cgo LDFLAGS: -ldl
#include <dlfcn.h>

double call_func(void* p, double a, double b) {
    double (*func)(double a, double b) = p;
    return func(a, b);
}
*/
import "C"
import "fmt"

func main() {

    handle := C.dlopen(C.CString("./Example_LvDLL.so"), C.RTLD_LAZY)
    if handle == nil {
        panic("Failed to open shared object.")
    }
    defer C.dlclose(handle)

    func_add := C.dlsym(handle, C.CString("Add"))
    if func_add == nil {
        panic("Could not found function pointer.")
    }

  var a, b float64 = 11.11, 22.2
    data := C.call_func(func_add, C.double(a), C.double(b)) // call LabVIEW DLL func

    fmt.Printf("data = %.2f\n", data)
}

ソースファイル

https://gitlab.com/alucky4416/example_lvlinux_so_and_cgo

参考

[Go言語から共有ライブラリ(so)をロードして使う] (https://qiita.com/neko-neko/items/e6bcc9e307646241e226)