ブログ - JavaでDXLIB2を動かす

JavaでDXLIB2を動かす

カテゴリ : 
雑記
2011-1-17 17:02
じゃばじゃばうるさいので、お試しとしてJavaからDXLIB2を動かすサンプルを作成してみた。
検証した環境は以下の通り。
お試しという事もあり、細かい事は抜きに動けばOKといったノリで条件付け。
  • DXLIB2を直接呼出すことはできないため、一旦ラッピング用DLLを作成する。
  • ラッピング関数名は使用するJavaのクラス名に依存。
  • unsigned short型やlong型はJava上でintとして使用する。
    必要に応じてラッピング関数内で型変換。
  • 全て同一フォルダ内に収める。
  • コンパイラ等へのパスは適宜通しておく。
スペースの都合かなり端折ってるが、こんな感じでやるのかなといった雰囲気だけ。
  1. Javaソース
    サンプルとして0~253のIDにPingを発行して結果をプロンプトに表示するソース。
    <SMPL1.java>
    public class SMPL1 {
      private native int DxOpenPort( String com, int br );
      private native boolean DxClosePort( int devid );
      private native boolean DxPing( int devid, int uid, int tout, char[] terr );
      static {
        System.loadLibrary( "dxtest" );  // 今回作成するラッピング用DLL(dxtest.dll)
      }
      public static void main( String args[] ) {
        String COMPORT = "\\\\.\\COM3";  // COMポート名
        int BUADRATE = 1000000;  // ボーレート
        int TIMEOUT = 50;  // タイムアウト
        char terr[] = new char[1];
        int devid, i;
        String msg = "Ping to ID:", mrk = "\n";
        SMPL1 me = new SMPL1();
        devid = me.DxOpenPort( COMPORT, BUADRATE );
        if ( devid != 0 ) {
          for ( i = 0; i < 253; i++ ) {
            if ( me.DxPing( devid, i, TIMEOUT, terr ) ) {
              System.out.printf( "\nPing to ID:%d...OK", i );
              mrk = "\n";
            }
            else {
              System.out.printf( "%sPing to ID:%d...NG(%x)", mrk, i, (int)terr[0] );
              mrk = "\r";
            }
          }
          if ( !me.DxClosePort( devid ) ) System.out.printf( "Close error\n" );
        }
        else
          System.out.printf( "Port not open\n" );
      }
    }

  2. ラッピング関数名の取得
    a). Javaソースをコンパイル(SMPL1.classを作成)。
    >javac SMPL1.java
    b). ヘッダファイルを作成(SMPL1.hを作成)。
    >javah -classpath . -d . SMPL1
    以下作成されるヘッダファイルの抜粋。
    <SMPL1.h>
    JNIEXPORT jint JNICALL Java_SMPL1_DxOpenPort  (JNIEnv *, jobject, jstring, jint);
    JNIEXPORT jboolean JNICALL Java_SMPL1_DxClosePort  (JNIEnv *, jobject, jint);
    JNIEXPORT jboolean JNICALL Java_SMPL1_DxPing  (JNIEnv *, jobject, jint, jint, jint, jcharArray)

  3. Cソース作成
    a). SMPL1.hをdxtest.cに変更。
    b). ラッピング関数の中身を作成。
    JavaとDLLの仲介役だが、相互の規約を気にしないと話にならない。とりあえず最低限必要なOpen/Close/Pingだけ作った。
    <dxtest.c>
    #define __MAKE_LIB__
    #include <stdio.h>
    #include <stdlib.h>
    #include <jni.h>
    #include "dxlib2.h"
    JNIEXPORT jint JNICALL Java_SMPL1_DxOpenPort
      (JNIEnv *env, jobject jobj, jstring pCom, jint br) {
      DXDEVICEID dev;
      char *port;
      int sz = (*env)->GetStringLength( env, pCom );
      // java文字列より取得
      const char *comPort = (*env)->GetStringUTFChars( env, pCom, 0 );
      port = (char *)malloc( sz + 1 );
      strcpy( port, comPort );
      port[strlen(port)] = 0x0;
      dev = DX_OpenPort( port, br );  // dxlib2.dllのDX_OpenPort()の呼出し
      // memory解放
      free( port );
      (*env)->ReleaseStringUTFChars( env, pCom, comPort );
      return (jint)dev;
    }
    JNIEXPORT jboolean JNICALL Java_SMPL1_DxClosePort
     (JNIEnv *env, jobject jobj, jint id) {
      return DX_ClosePort( (DXDEVICEID)id );
    }
    JNIEXPORT jboolean JNICALL Java_SMPL1_DxPing
      (JNIEnv *env, jobject jobj, jint devid, jint id, jint tout, jcharArray terr) {
      TDxErrorCode  err;
      BOOL      bResult;
      UCHAR   uID;
      jchar        *arrays; // local領域
      int             sz;         // 配列size
      jboolean jbl;         // isCopy
      uID = (UCHAR)(id & 0x00ff);
      bResult = DX_Ping( (DXDEVICEID)devid, uID, tout, &err );
      // 配列の取得
      arrays = (*env)->GetCharArrayElements( env, terr, &jbl );
      if ( (*env)->GetArrayLength( env, terr ) > 0 ) arrays[0] = err;
      // 配列の解放(Javaへ適用)
      (*env)->ReleaseCharArrayElements( env, terr, arrays, 0 );
      return bResult;
    }

  4. DLL作成
    a). dxtest.cをDLLにする。
    >gcc -shared -o dxtest.dll dxtest.c -l dxlib2 -Wl,-kill-at -I Javaのincludeパス -I Javaのincludeパス\win32 -L .
    Javaのincludeパスに空白が含まれている場合はダブルクォーテーションで括る等の措置を講じるべし。

  5. 実行
    a). 以下のDLLとクラスファイルが同じフォルダに存在していることを確認。
    SMPL1.class  dxtest.dll  dxlib2.dll
    b). おもむろにコマンドプロンプトで実行
    >java SMPL1
    実行結果はこんな感じになるだろうか。

雑感、何が楽しいのかさっぱり・・・。

トラックバック

トラックバックpingアドレス http://www.besttechnology.co.jp/modules/d3blog/tb.php/60