Processing(Java)からSwiftで書いたプログラムを呼び出す

[Processing](https://processing.org/) を使ってユーティリティ系のソフトを作っていると、どうしてもかゆいところに手がとどかない(システム環境設定系とか)

Swiftで実装すればAPIを叩くのに苦労はしないが、
Java側で `Runtime#exec` とか `ProcessBuilder` を使うのはなんか違う気がするので、
どうにかしてして、Javaで実装されたメソッドのようにSwiftで実装した関数を叩きたい！

# JNA(Java Native Access)
Processingの実体はPAppletクラスを継承したJavaクラスであるため、
Javaの文法、資産を利用することができる

Javaには、JNI(Java Native Interface)と呼ばれる、C/C++などで実装されたネイティブコードと連携する仕組みがある。
このJNIを利用すれば、Swiftで実装したネイティブコードを呼び出されるのではと思うが、
このJavaとC/C++を繋ぐJNIを書くのがマヂ無理
(パッケージ名を含めた関数名をつけた関数をつくったり...)

※ Swiftの実装を呼び出すには結局SwiftとJavaの間にCのコードを挟まないといけない
*Write & call Swift code using Java’s JNI*
https://stackoverflow.com/questions/27628385/write-call-swift-code-using-java-s-jni

あー、**Javaからネイティブコードを呼びたい** 
けど、**JNIは書きたくない**

そんなときは **JNA(Java Native Access)** を使おう
なんかよしなにやってくれるらしい！

JNAに関してはこのあたりを参照されたし
https://qiita.com/everylittle/items/b888cbec643f14de5ea6

# Swiftのソースからダイナミックリンクライブラリを生成
兎にも角にも、Javaから呼び出したいメソッドを作ります

```swift:hello.swift
import Darwin.C

@_cdecl("hello")
public func hello() {
    print("Hello")
    fflush(stdout)
}
```
上のプログラムは標準出力に `Hello` と表示する関数の実装
ポイントは **1.呼び出し規約を設定する**,**2.publicにする** です

`fflush(stdout)` がないとprintされないらしいので入れておきましょう
*Printf from native code appears only at the end of the java app*
https://stackoverrun.com/ja/q/3379588

このままではソースのままなのでコンパイルしましょう
上のプログラムからダイナミックリンクライブラリ(MacOSだとlib*.dylib)を生成します

```bash:ダイナミックリンクライブラリを生成
swiftc -emit-library hello.swift
```

ターミナルで上のコマンドを実行すると `lib + ファイル名(拡張子なし) + .dylib` の
ダイナミックリンクライブラリが生成されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/8c877d6f-b654-c151-5452-aa5db8dca910.png)

nmコマンドで確認すると `hello`関数がグローバルセクションにあってなんか呼べそうな気がしてきますね

```bash:nmコマンドで確認
cha84rakanal$ nm libhello.dylib 
0000000000000e40 T _$S5helloAAyyF
                 U _$S6Darwin6stdoutSpySo7__sFILEVGvg
                 U _$SSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC
                 U _$SSSN
                 U _$Ss27_allocateUninitializedArrayySayxG_BptBwlFyp_Tg5
                 U _$Ss5print_9separator10terminatoryypd_S2StF
                 U _$Ss5print_9separator10terminatoryypd_S2StFfA0_
                 U _$Ss5print_9separator10terminatoryypd_S2StFfA1_
0000000000000fac s ___swift_reflection_version
                 U __swift_FORCE_LOAD_$_swiftDarwin
0000000000001060 s __swift_FORCE_LOAD_$_swiftDarwin_$_hello
                 U _fflush
0000000000000e30 T _hello
                 U _swift_bridgeObjectRelease
                 U _swift_bridgeObjectRetain
                 U dyld_stub_binder
cha84rakanal$ 
```

# 実際にJava側からSwiftで実装した関数を呼び出す
さて実際にProcessing(Java)側から先程作った `Hello関数` を呼び出してみます
スケッチのdataディレクトリに先に生成したダイナミックリンクライブラリを入れて、次のスケッチで動かします！

```Java:JNAProcessing.pde
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

public interface SwiftLib extends Library {
    void hello();
}

SwiftLib mylib;

void setup(){
    mylib = (SwiftLib) Native.loadLibrary(dataPath("libhello.dylib"), SwiftLib.class);
    mylib.hello();
}

void draw(){
}
```

ポイントは、

1. JNA関連のライブラリをインポート
1. com.sun.jna.Libraryを継承したインターフェースを定義(中に作成した関数の定義)
1. `Native#loadLibrary` でダイナミックリンクライブラリを読み込み、ライブラリ名だけだと、Javaが参照しているダイナミックライブラリのパスをみにいく、絶対パスで入れられると確実

これでHelloと表示されたらOK！ あとは何でも好きな処理をSwiftで実装するだけ！
それでは、よいProcessing Life

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/d7f16938-fb8a-ca4e-2ab7-9bd9f8d32367.png)