ホームへ戻る

2.4 JavaのStringをDLLで解釈する


JavaのStringはそのままDLLで使えませんし、jstringをconst char*にすると、他バイト文字が文字化けします。
これはJavaがUnicodeなのに対し、VC++がShift-JISなためです。

従って以下の手順で正常にDLLで他バイト文字が読めるようにします。
LoadGraph(const char*);
の実装を例に紹介します。

1.
Java側で、StringをShift-JISにしたbyte配列を渡します。


private static native int LoadGraph (byte[] FileName);
public static int LoadGraph(String fileName){
	try {
		return LoadGraph(fileName.getBytes("Shift-JIS"));
	} catch (UnsupportedEncodingException e) {
		return ERROR;
	}
}

2.
DLL側は、受け取ったbyte配列から文字列を取り出します。
しかし、取り出しただけでは、終端記号が入っていないので、mallocで配列+1の要素ほど確保して、内容をコピーし、
終端記号を入れた上で利用します。もちろん利用後は解放しないといけないので、以下のようになります。


JNIEXPORT jint JNICALL Java_jdx_Dx_LoadGraph			
(JNIEnv *env, jobject obj, jbyteArray string)
{
	jboolean mIsCopy;
	char* mBufBytes = (char *)env->GetByteArrayElements(string, &mIsCopy);
	int   mLen = env->GetArrayLength(string);
	char* mStringc = (char *)malloc(mLen+1);
	memcpy(mStringc, mBufBytes, mLen);
	mStringc[mLen] = '\0';

	int ret = LoadGraph( mStringc );

	if (mIsCopy == JNI_TRUE){
		env->ReleaseByteArrayElements(string, (jbyte*)mBufBytes, 0);
	}
	free(mStringc);
	return ret;
}

しかし、赤部と青部はお決まり処理なのに、毎回こんなことを書いていたら大変です。そこで・・・

3.
文字列を扱う部分をクラス化します。
よく見たら、上の処理は、赤がコンストラクタ、青がデストラクタで良さそうです。
従って以下のようなクラスを作ってみます。

class BytesString {
public:
	BytesString(JNIEnv *env, jbyteArray string){
		mEnv = env;
		mString = string;
		mBufBytes = (char *)env->GetByteArrayElements(mString, &mIsCopy);
		mLen = env->GetArrayLength(string);
		mStringc = (char *)malloc(mLen+1);
		memcpy(mStringc, mBufBytes, mLen);
		mStringc[mLen] = '\0';
	}
	~BytesString(){
		if (mIsCopy == JNI_TRUE){
			mEnv->ReleaseByteArrayElements(mString, (jbyte*)mBufBytes, 0);
		}
		free(mStringc);
	}
	char *GetString(){
		return mStringc;
	}

private :
	JNIEnv*		mEnv;
	char*		mBufBytes;
	char*		mStringc;
	jbyteArray	mString;
	jboolean	mIsCopy;
	int			mLen;
};

こうすれば、先ほどのLoadGraphの実装は以下のようになります。

JNIEXPORT jint JNICALL Java_jdx_Dx_LoadGraph			
(JNIEnv *env, jobject obj, jbyteArray string)
{
	BytesString bstr(env, string);
	return LoadGraph(bstr.GetString());
}

非常にシンプルになりました。
こちらにプロジェクトを置いておきます。
DXライブラリ自体は入っていませんので、DXライブラリのincludeパスはご自分の環境に従って設定して下さい。

→分からないことがあれば掲示板で質問して下さい


Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License.

- Remical Soft -