Dart Advent Calendar 2019 の 記事です。
Dart の Native Interface に ついての記事です。
Go や C言語の機能をDartで利用する方法について解説します。また、すぐに Native Interface を試せるように、 Docker Image を 用意しました。
Native Interface とは : C言語 の ライブラリーを使用することができる機能です
C言語 の ライブラリーを使用することができる機能です。ただし、C言語と言ってもC言語でのライブラリーに閉じたものではないです。
Go言語 や Rust言語などのシステム言語は、Shared Libraryを作成することができます。
この Shared Library 経由すれば、Dartで GoやRustなどの機能も利用できます。
とても便利 : OSの機能をフルに使える
Dartは、まだまだライブラリーが不足している状態です。ですので、C言語で開発されたライブラリーや、Goで開発されたライブラリーを利用する必要があります。
Native Interface によち、 Dart がより便利になります。
開発環境 : Docker 環境を用意しました。
Code-Server という VSCode が オンライン上で動作する エディターを含めました。
このため、 Dockerを起動すれば、即、開発ができます。
FROM ubuntu:20.04
WORKDIR /works
# install dart
RUN apt-get update
RUN apt-get install -y wget gnupg1
RUN apt-get install apt-transport-https
RUN sh -c 'wget -qO- https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -'
RUN sh -c 'wget -qO- https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list'
RUN apt-get update
RUN apt-get -y install dart
# install go
RUN apt-get install software-properties-common -y
#RUN add-apt-repository ppa:longsleep/golang-backports
RUN apt-get update
RUN apt-get install golang-go -y
RUN apt-get install git -y
RUN go get github.com/ramya-rao-a/go-outline
RUN go get github.com/mdempsky/gocode
RUN go get github.com/uudashr/gopkgs/cmd/gopkgs
RUN go get github.com/sqs/goreturns
RUN go get github.com/rogpeppe/godef
# install c
RUN apt-get install musl-dev -y
# code-server
RUN wget https://github.com/cdr/code-server/releases/download/2.1692-vsc1.39.2/code-server2.1692-vsc1.39.2-linux-x86_64.tar.gz
RUN tar -xzf code-server2.1692-vsc1.39.2-linux-x86_64.tar.gz -C ./ --strip-components 1
RUN /works/code-server --install-extension Dart-Code.dart-code
RUN /works/code-server --install-extension ms-vscode.go
RUN /works/code-server --install-extension ms-vscode.cpptools
WORKDIR /app
ENV PATH=${PATH}:/lib/dart/bin
ENV PATH="${PATH}:/root/.pub-cache/bin"
RUN pub global activate webdev
RUN pub global activate stagehand
CMD ["/works/code-server", "--auth","none", "--host","0.0.0.0","--port","8443", "/app"]
version: '3'
services:
app:
build: ./app
ports:
- "8080:8080"
- "8443:8443"
volumes:
- ./app:/app
# - /var/run/docker.sock:/var/run/docker.sock
command: /works/code-server --auth none --host 0.0.0.0 --port 8443 /app
具体的には、github を参照してください。
開発環境を起動する。
$ git clone https://github.com/kyorohiro/advent-2019-code-server.git
$ cd advent-2019-code-server/extra/dart_fmi_and_go_and_c
$ docker-compose build
$ docker-compose up -d
ブラウザーで、http://127.0.0.1:8443/
を開く
Go で Shared Library を 作成する。
VSCode->File(Menu)->/app/wgo
に移動する。
package main
import "C"
import "fmt"
//export PrintHello
func PrintHello() {
fmt.Print("Hello,World")
}
func main() {}
Goの PrintHello 関数を、Dart から呼ばれる予定です。
$ go build -o libhello.so -buildmode=c-shared hello.go
とすると、libhello.h
と libhello.so
というファイルができます。
Dart で読み込む前に、C言語から読み込んでみましょう。
#include <stdio.h>
#include "libhello.h"
int main(int argc, char const *argv[])
{
PrintHello();
return 0;
}
$ gcc -Wall -o main_hello.exe main_hello.c -L. -lhello
$ LD_LIBRARY_PATH=. ./main_hello.exe -L. -lhello
Hello,World
おっ!! 上手く動作しました。
Dart から読み込んでみる。
VSCode->File(Menu)->/app/wdart
に移動する。
import 'dart:ffi' as ffi;
typedef PrintHello_func = ffi.Void Function();
typedef PrintHello = void Function();
void main(List<String> arguments) {
var path = "/app/wgo/libhello.so";
ffi.DynamicLibrary dylib = ffi.DynamicLibrary.open(path);
final PrintHello hello = dylib
.lookup<ffi.NativeFunction<PrintHello_func>>('PrintHello')
.asFunction();
hello();
}
$ dart ./bin/main.dart
Hello,World
PS
C言語の環境も用意しました。
先ほどの、github レポジトリーから見れます。
Go言語で開発された機能をDartでフルに利用できます。ので、Dart から ほぼなんでも出来る状態になりました。
FMIがサポートされたことで、気軽に Native Interface を書けるようになったと思います。
サーバーサイド向けでしたら、開発には、Docker Image などが便利だと思います。
今回、使用した Code-Server について、下記 Advent にて
20回以上に分けて解説していますので、興味ある方は、ご参照ください。
※ Docker Image として固めてHub に 配置するなどすれば、必ず動作するようになりますが、Image には固めていません。個人利用する際は、 Image に固めて保管しておくことをお勧めします。
Code