MESシリーズ--(2)JNA使用紹介


JNA:java native access! JNIのアップグレード版だと言われていますが、実際に使った後、そうではないことに気づきました.JNAにはJNIが強くなく、場合によってはJNIより簡単に使えます.前編のJNIは入門して、みんなはJNIを編纂してローカルコードにアクセスするステップがすでにとても規則的で堅苦しいことを見ることができて、もしあなたが事前にローカルコードの例えばdllファイルがあるならば、“おめでとう”あなた、あなたは1階をカプセル化しなければならなくて、JNIの中で、あなたのローカルコードの関数の名前、パラメータはすべて求めます!JNAはここで突破して、あなたは先にローカルコードを持って、それからJavaコードを書いてローカルコードに適応することができて、JNIの中でローカルコードにあなたのJavaコードに適応させるのではありません.
私は実際の応用では、ローカルコード(ハードウェアメーカーが提供するハードウェアドライバ)を先に持っていることが多いので、JNAはやはり一定の役割を果たすことができます.直接例を挙げましょう.私たちは今、ICカードリーダーを持っています.ハードウェアメーカーはハードウェアにアクセスするdllファイル(Windowsフラットデスク)を提供しています.その中の対応する関数は次のように定義されています.
#define MAX_BUFFER_SIZE 2048

#define MYLIBAPI  extern   "C"   __declspec( dllexport )  

MYLIBAPI char* readCardId(int, int);

関数readCardIdはこのdllファイルのエクスポート関数で、2つのintタイプのパラメータを受け入れ、char配列、すなわちカード番号を返します.この関数はJNI仕様に合致しません.JNIを使用してこの関数にアクセスする場合は、この関数を転送するためにパッケージ化する必要があります.しかし、JNAがあって、私たちは別の選択肢を持っています.私たちは直接Javaコードを使うことができて、まずこのJavaコードを貼って、それからみんなに分析します:
package cn.test;

import com.sun.jna.Library;
import com.sun.jna.Native;

public interface IReadCard extends Library{
	
	public static final IReadCard INSTANCE = (IReadCard)

	Native.loadLibrary("ICCardReader", IReadCard.class);
	
	String readCardId(int antenum, int readcount);
}

これはJavaインタフェースで、Libraryから継承され、JNA関連jarパッケージ(私のリソースにはダウンロードがあります).インタフェースには関数、String readCardId(int,int)が定義されています.この関数はdllファイルの関数と対応する必要があります.(JNIではJavaとC++のタイプ対応関係が定義されています.JDK関連ドキュメントを参照してください).このインタフェースでは、JNAのクラスNative.loadLibraryを介して関連するdllファイルをロードします.この例ではICCardReaderであり、インタフェースインスタンスオブジェクトを返します.インスタンスオブジェクトへのメソッド呼び出しはローカルメソッドに移行します.ローカルコードライブラリファイルをロードすると、接尾辞を付けないでください.これはプラットフォームの無関係で、Windowsプラットフォームの下で、ライブラリファイルはdllで、Linuxの下でso接尾辞です.
JNAの作成は確かに速いです.Javaを直接書いてローカルコードに合わせるだけでいいからです.書き終わったら、呼び出すことができます.しかし、場合によっては、ローカルコードの関数のパラメータタイプが複雑で、Java側と対応できないか、難しい場合は、JNA側で使用するためのパラメータの簡単な関数を提供することをお勧めします.
もう少しJNAについて話しましょう.JNAの下部は完全にJNIに基づいています.JNAが提供するjarパッケージが担当しているのは、このような呼び出し間変換です.実は最後の呼び出しプロセスはJNIのものです.だからJNAの効率はJNIより低い.また、JNAはローカルコードに要求がないため、ローカルコードはJavaエンドコードをコールバックすることができず、JNIのローカルコードはJavaのコードをコールバックすることができる.
まとめると、JNAは関数パラメータと戻り値の比較的簡単なローカルコードの呼び出しに非常に便利で、Javaエンドコードをコールバックすることはできません(これは実際にはあまり使われていません).ローカルコードのパラメータと戻り値が複雑な場合は、JNAを使用してもパッケージ化することをお勧めします.
最後に、プラットフォーム間呼び出しで、最も難しいのはデータ型の変換です.ローカルコードライブラリがJavaプラットフォームのために呼び出されていると思ったら、関数パラメータの簡単さを事前に保証しましょう.複雑なパラメータをたくさん使わないでください.