JNAeratorを使用したJAVAと共有ライブラリの連携まとめ

# JNAeratorを使ってlinuxの共有ライブラリと構造体のデータ受け渡しをする方法の備忘録
Linuxの共有ライブラリとJAVAでデータのやり取りを行うときに構造体を使うのが思ったより簡単にできましたので、そのやり方をメモしておきます。

##JNAeratorによる操作
### JNAeratorをダウンロードします
ダウンロードはこちらから
https://code.google.com/archive/p/jnaerator/downloads

### JNAeratorを実行する
xxxxxのところは、バージョン情報や日付などが入っていました。
java -jar jnaerator-xxxxxx-SNAPSHORT-xxxxx.jar

### 画面が起動したらヘッダファイルを貼り付けます
起動してコードを貼り付けた画面がこちら。(Raspberry Pi上で実行しています)
#![2016-08-14-142143_1366x768_scrot.png](https://qiita-image-store.s3.amazonaws.com/0/136933/81c15d8b-8ac5-8b41-0dc4-8d10141d9bf0.png)

### JNAerate !ボタンを押す
JNAerate!ボタンを押した後の結果がこちら。右側の画面にJAVAのコードが生成されました。
![2016-08-14-144118_1366x768_scrot.png](https://qiita-image-store.s3.amazonaws.com/0/136933/b35f0597-5107-dc3a-ff78-2be3c465ab65.png)

### ファイルに保存する
右側の画面に表示されているコードをコピーしてファイルに保存します。ファイル名やクラスは「JNAerator class:」に表示されるのでそのまま使用しましょう。ただし、この時packageを使用したくなかったので、ファイル名はその部分を削除してSUBGHZ_MAC.javaにしました。

## jarファイルのインストール
ここまでの作業で作成されたコードを使用するためには、ライブラリのインストールが必要です。
ライブラリのダウンロードはこちら
http://www.java2s.com/Code/Jar/j/Downloadjnaeratorruntime011jar.htm

ダウンロードしたライブラリはunzipして、javaのライブラリフォルダに保存します。
コピー先のフォルダは環境によって変わります。これはRaspberry Pi3の場合です。
$ unzip jnaerator-runtime-0.11.jar.zip
$ sudo cp jnaerator-runtime-0.11.jar /usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/jre/lib/ext/

## 作成したライブラリの修正
### 作成した「SUBGHZ_MAC.java」を確認します。
一部直したほうが良いコードが有りましたので修正をしました。
+ ファイルの先頭行に含まれているpackageを消しました。
+ time_tのところがうまく変換出来ていないようです。linuxのtime_tは32bitのunsigned long型なので、NativeLongに変更しました。

## 実行するJAVAの作成
### このようなコードを作成しました

```
//package com.lapis_semi.lazurite.io;
//import com.ochafik.lang.jnaerator.runtime.Structure;
import java.util.Arrays;
import java.util.List;
import java.util.Date;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.NativeLong;

public class LibraryTest {

	interface LazuriteLib extends Library {
		// load library
		LazuriteLib INSTANCE = (LazuriteLib) Native.loadLibrary("lazurite",LazuriteLib.class);

		// functions
		int lazurite_close();
		int lazurite_link(short addr);
		int lazurite_setRxAddr(short tmp_rxaddr);
		int lazurite_setPanid(short tmp_panid);
		int lazurite_setCh(byte ch);
		int lazurite_open();
		int lazurite_write(String payload, short size);
		int lazurite_available();
		int lazurite_read(char[] payload, short[] size);
		int lazurite_readRaw(SUBGHZ_MAC mac);
		int lazurite_getRxTime(Pointer tv_sec,Pointer tv_nsec);
		int lazurite_getRxRssi(Pointer rssi);
		int lazurite_getTxRssi(Pointer rssi);
		int lazurite_test(byte[] payload,short[] size);
	}
	public static void main(String[] args)
	{
		int result;
		LazuriteLib lazurite = LazuriteLib.INSTANCE;

		SUBGHZ_MAC mac = new SUBGHZ_MAC();
		
		byte ch = 36;
		short panid = (short)0xabcd;
		result = lazurite.lazurite_open();
		result = lazurite.lazurite_setCh(ch);
		result = lazurite.lazurite_setPanid(panid);
		System.out.println("result="+Integer.toString(result));
		do {
			result = lazurite.lazurite_readRaw(mac);
		} while(result <= 0);
		try {
			byte[] raw = mac.raw.getByteArray(0,mac.raw_len);
			String payload = mac.payload.getString(0);
			long t = (mac.tv_sec.longValue() & 0x0ffffffff)*1000 + (mac.tv_nsec.longValue() & 0x0ffffffff)/1000000;
			int rx_addr = mac.rx_addr[1] & 0x00ff;
			rx_addr = (rx_addr << 8) + (mac.rx_addr[0]&0x00ff);
			int tx_addr = mac.tx_addr[1] & 0x00ff;
			tx_addr = (tx_addr << 8) + (mac.tx_addr[0]&0x00ff);
			int rssi = mac.rssi & 0x0000ff;
			//rssi = rssi & 0x000000ff;
			
			System.out.print(new Date(t) + "\t" +
					Integer.toHexString(rx_addr) + "\t" + 
					Integer.toHexString(tx_addr) + "\t" + 
					Integer.toString(rssi) + "\t" + 
					payload);
		} catch (Exception e) {}
		result = lazurite.lazurite_close();
	}
}
```

### 共有ライブラリを使用するための宣言
importするライブラリの宣言と関数の宣言はこの部分になります。

```
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.NativeLong;

	interface LazuriteLib extends Library {
		// load library
		LazuriteLib INSTANCE = (LazuriteLib) Native.loadLibrary("lazurite",LazuriteLib.class);

		// functions
		int lazurite_close();
		int lazurite_link(short addr);
		int lazurite_setRxAddr(short tmp_rxaddr);
		int lazurite_setPanid(short tmp_panid);
		int lazurite_setCh(byte ch);
		int lazurite_open();
		int lazurite_write(String payload, short size);
		int lazurite_available();
		int lazurite_read(char[] payload, short[] size);
		int lazurite_readRaw(SUBGHZ_MAC mac);
		int lazurite_getRxTime(Pointer tv_sec,Pointer tv_nsec);
		int lazurite_getRxRssi(Pointer rssi);
		int lazurite_getTxRssi(Pointer rssi);
		int lazurite_test(byte[] payload,short[] size);
	}
```

### 構造体内部のメンバー変数の読み出し方
#### Pointer
仕様はこちら(https://jna.java.net/javadoc/com/sun/jna/Pointer.html)
文字列の取得: 　String payload = = mac.payload.getString(0);
 0のところは抽出するデータのオフセット
ByteArrayの取得: byte[] raw = mac.raw.getByteArray(0,mac.raw_len);
 Pointer.getByteArray(offset,size);
#### NativeLong
  long t = mac.tv_sec.longValue()
#### 注意事項
次のようにC言事は異なる点が多々あるので、共有ライブラリからデータを取得した後にJAVAのデータ型に直したほうが良いです。
+ Javaにはunsigned型が無い
+ データ型のビット長がJAVAとC言語は異なる