Code-Server x Dart with ffi x Go x Clang

This is an article of Dart Advent Calendar 2019.

An article about Dart's Native Interface. Learn how to use Go and C features with Dart. We've also prepared a Docker Image so you can try out the Native Interface right away.

Native Interface: A feature that allows you to use C language libraries

https://dart.dev/guides/libraries/c-interop

This is a function that allows you to use a C language library. However, C language is not closed to the library in C language.

System languages such as Go and Rust can create Shared Libraries.

You can also use features such as Go and Rust with Dart via this Shared Library.

Very convenient: Full use of OS functions

Dart is still running out of libraries. Therefore, it is necessary to use the library developed in C language or the library developed in Go. The Native Interface makes Dart more convenient.

Development environment: We have prepared a Docker environment.

We have included an editor called Code-Server that runs VS Code online. Therefore, if you start Docker, you can start development immediately.

https://github.com/kyorohiro/my-code-server/tree/master/w/dart_and_go_and_c/

https://github.com/kyorohiro/advent-2019-code-server/tree/master/extra/dart_ffi_and_go_and_c

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"]

docker-compose.yml


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 

Specifically, see github.

Start the development environment.

$ 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

Open http://127.0.0.1:8443/ in your browser

Screen Shot 2019-12-22 at 20.31.13.png

Create a Shared Library in Go.

Go to VSCode-> File (Menu)-> / app / wgo.

hello.go


package main

import "C"
import "fmt"

//export PrintHello
func PrintHello() {
	fmt.Print("Hello,World")
}

func main() {}

Go's PrintHello function will be called by Dart.

$ go build -o libhello.so  -buildmode=c-shared  hello.go

Will create the files libhello.h and libhello.so. Let's load it from C before loading it with Dart.

main_hello.c


#include <stdio.h>
#include "libhello.h"


int main(int argc, char const *argv[])
{
  PrintHello();
  return 0;
}

Terminal



$ gcc -Wall -o main_hello.exe main_hello.c -L. -lhello
$ LD_LIBRARY_PATH=. ./main_hello.exe -L. -lhello
Hello,World

Oops !! It worked fine.

Try loading from Dart.

Go to VSCode-> File (Menu)-> / app / wdart.

bin/main.dart


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();
}


Terminal


$ dart ./bin/main.dart
Hello,World

PS

We also prepared a C language environment. You can see it from the github repository earlier.


Get full access to features developed in Go with Dart. So, from Dart, I can do almost anything. With the support of FMI, I think it's easier to write Native Interfaces.


If it is for the server side, I think that Docker Image etc. is convenient for development.

About the Code-Server used this time, in the following Advent The explanation is divided into more than 20 times, so if you are interested, please refer to it.

https://qiita.com/advent-calendar/2019/code-server

Code

https://github.com/kyorohiro/my-code-server/tree/master/w/dart_and_go_and_c/

https://github.com/kyorohiro/advent-2019-code-server/tree/master/extra/dart_fmi_and_go_and_c

Recommended Posts

Code-Server x Dart with ffi x Go x Clang
Python with Go
GRPC starting with Go server and Dart client
Call the C function with dart: ffi and call the Dart function callback