S-JIS[2007-10-07] 変更履歴

jnifタスク

javahによって生成されたヘッダーファイル”内の関数を列挙するタスクです。→タスクのアーカイブ(hmant.jar)


javahによって生成されたヘッダーファイルでは、以下のように関数が宣言されています。

JNIEXPORT jstring JNICALL Java_jp_hishidama_win32_api_WinBase_FormatMessage
  (JNIEnv *, jclass, jint);

この「JNICALL」がある行の、その部分より後ろをカンマ付きで出力するだけです。…。


jnifの説明

パラメータ

属性 説明 必須
destdir ファイルの出力先ディレクトリを指定する。 No; デフォルトは、入力ファイルと同じ場所
prefix 出力ファイルの接頭辞を指定する。 No; デフォルトは、「jni_func.
suffix 出力ファイルの接尾辞を指定する。 No; デフォルトは、「.txt
force (タイムスタンプを比較しない)強制上書きの有無を指定する。 No; デフォルトは、no

ネストする要素として指定されるパラメータ

fileset

FileSetは、抽出対象のファイルを指定する。


使用例

build.xml:

	<typedef resource="typedef.properties" classpath="lib/hmant.jar" />
	<target name="jni_function">
		<jnif prefix="jni_check." force="no">
			<fileset dir="C:\vc2005\hmwin32">
				<include name="jp_hishidama_win32_api_*.h" />
			</fileset>
		</jnif>
	</target>

出力結果(jni_check.jp_hishidama_win32_api_WinBase.h):

	Java_jp_hishidama_win32_api_WinBase_GetLastError,
	Java_jp_hishidama_win32_api_WinBase_FormatMessage,

VC++では宣言なしでも関数を定義できるしオーバーロードもできるので、ヘッダーファイルで指定した関数と違う関数を定義してもエラーになりません。(唯一、戻り値の型が違うときだけエラーになるけど)
なので、関数の数が多くて実装漏れがあったり一度作った関数の引数を変えたが修正を間違った場合などにもコンパイルエラーにはならず、実行時に落ちて発覚するという最悪の状態になってしまいます。

解決策としては、C++のコンパイルの範囲で関数を使用してやること。
関数をどこかで使っていれば、その関数が定義されていない場合にリンクエラーになるので分かります。
通常の関数呼び出しの他にグローバルに関数ポインターを保持するだけでも「使う」ことになるので、配列変数を定義して、その初期値として関数ポインターを書いてやればよいということです。

jni_check.cpp:

#ifdef _DEBUG

//javahによって生成されたヘッダーファイル
#include "jp_hishidama_win32_api_WinBase.h"
#include "jp_hishidama_win32_api_WinUser.h"

void *jni_func_check[] = {
//jnifによって生成した関数名
#include "jni_check.jp_hishidama_win32_api_WinBase.h"
#include "jni_check.jp_hishidama_win32_api_WinUser.h"
};

#endif

デバッグビルドのときだけ配列変数を定義します。実装漏れのJNI関数があるとリンクエラーになります。
リリースビルドではコンパイル対象外となるので、余計な領域は消費しません。


自作Antタスクへ戻る / 自作ソフトへ戻る / 技術メモへ行く / 独自タスクの作り方へ行く
メールの送信先:ひしだま