JNI
C等で作成したOSネイティブのライブラリを呼び出す技術。JNIから呼べるのはJNI用に作成されたライブラリのみ。WindowsではJNIでは、JNI用に作られたDLLしか操作できず、通常のDLLを直接Javaから操作することはできない。Windows APIを使うには、JNI用に作成されたDLLを呼び出し、JNIのDLLの中からネイティブAPIを呼び出す。
サンプルコード
ODBCCP32というDLLを操作してODBCデータソースを作成する。
Javaのソースを書く
package jp.paulownia.odbc; public class JOdbccp32 { /** クラスロード時にDLLもロードします。 */ static { System.loadLibrary("JOdbccp32"); } /** ユーザーデータソースの追加 */ public static final short ODBC_ADD_DSN = 1; /** ユーザーデータソースの編集 */ public static final short ODBC_CONFIG_DSN = 2; /** ユーザーデータソースの削除 */ public static final short ODBC_REMOVE_DSN = 3; /** システムデータソースを追加 */ public static final short ODBC_ADD_SYS_DSN = 4; /** システムデータソースを編集 */ public static final short ODBC_CONFIG_SYS_DSN = 5; /** システムデータソースを削除 */ public static final short ODBC_REMOVE_SYS_DSN = 6; /** デフォルトDSNを削除 */ public static final short ODBC_REMOVE_DEFAULT_DSN = 7; /** SQLConfigDataSource関数を呼び出します。 */ public native boolean callSQLConfigDataSource(short op, String driver, String dsn); }
javacでコンパイル。
C:¥javaSrc¥jni> javac jp/paulownia/odbc/JOdbccp32.java
生成したクラスからC言語用のヘッダファイルを作成します。
C:¥javaSrc¥jni> javah -jni jp.paulownia.odbc.JOdbccp32
上記のコマンドでjp_paulownia_odbc_JObbccp32.hというファイルが作られる(ファイル名はクラスに合わせて変わる)。このヘッダファイルを使ってC++でJOdbccp32.dllを作成する。 dllの作成方法は、こちらのサイト等を参考にする。C++のソースは以下のようになる。
#include "jp_paulownia_odbc_JOdbccp32.h" #include <windows.h> #include <odbcinst.h> #include <stdio.h> JNIEXPORT jboolean JNICALL Java_jp_paulownia_odbc_JOdbccp32_callSQLConfigDataSource (JNIEnv *env, jobject jobj, jshort op, jstring db, jstring dsn) { int dsnLen = env->GetStringLength(dsn); char* cDsn = (char*)calloc(dsnLen * 2 + 1, sizeof(char)); const jchar* jcDsn = env->GetStringChars(dsn, NULL); WideCharToMultiByte(CP_ACP, 0, jcDsn, dsnLen, cDsn, dsnLen * 2 + 1, NULL, NULL); env->ReleaseStringChars(dsn, jcDsn); int dbLen = env->GetStringLength(db); char* cDb = (char*)calloc(dbLen * 2 + 1, sizeof(char)); const jchar* jcDb = env->GetStringChars(db, NULL); WideCharToMultiByte(CP_ACP, 0, jcDb, dbLen, cDb, dbLen * 2 + 1, NULL, NULL); env->ReleaseStringChars(db, jcDb); BOOL rtn = SQLConfigDataSource(NULL, op, cDb, cDsn); free(cDb); free(cDsn); return rtn; }
作成したdllをカレントディレクトリに設置し、テストコードを実行。
import jp.paulownia.odbc.JOdbccp32; public class Test { public static void main(String[] hoge) { JOdbccp32 odbc = new JOdbccp32(); String dsn = "DSN=ac¥0Description=pos data sample¥0DBQ=c:¥¥javaSrc¥¥pos.mdb"; String driver = "Microsoft Access Driver (*.mdb)"; odbc.callSQLConfigDataSource(JOdbccp32.ODBC_ADD_DSN, driver, dsn); } }
実行する。
C:¥javaSrc¥jni> java Test true
Access用の新しいODBCデータソースがユーザDSNに作成される。Access以外にもSQL ServerなどのODBCデータソースも作ることができる。
2バイト文字や特殊文字を扱うのが多少面倒。1バイト文字だけならば、jstringからchar*への変換は、GetStringUTFChars関数を使えば良い。しかし、JavaのStringがヌル文字(¥0)などの特殊文字や2バイト文字を含む場合、上記のようにGetStringChars関数を使ってwcharとして取得し、charに変換しなければならないようだ。当然だがC++をしっかり学習しないと何もできない。