jniステップテスト

6054 ワード

環境:win 7 64,vs 2008,eclipse 3.7, jdk1.6
JAvaコードは次のとおりです.
package cyper.jni;

public class Test {
	public native int sumArray(int[] arr);
	public native String getString();
	public native String[] getStringArray();
	
	public static native int[][] initInt2DArray(int size);
	
	public static void main(String[] args) {
		Test t = new Test();
		
		// String 
		System.out.println(t.getString());
		
		// int 
		int arr[] = new int[]{1,2,3,4,5,6,7,8,9,10};
		System.out.println(t.sumArray(arr));
		
		// 
		int[][] i2arr = initInt2DArray(3);
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				System.out.print(" " + i2arr[i][j]);
			}
		}
		System.out.println();
		
		// String 
		String[] str = t.getStringArray();
		for (int i = 0; i < str.length; i++) {
			System.out.println(str[i]);
		}
		
	}
	
	static {
		System.loadLibrary("test");
	}
}

cppコードは以下の通りです.
#include "cyper_jni_Test.h"
#include <windows.h>
#include <vector>
/*
 * Class:     cyper_jni_Test
 * Method:    sumArray
 * Signature: ([I)I
 */
JNIEXPORT jint JNICALL Java_cyper_jni_Test_sumArray
  (JNIEnv * env, jobject obj, jintArray arr)
{
	//version 1
	/*
	jint buf[10];
	jint i, sum = 0;
	env->GetIntArrayRegion(arr,0,10,buf);

	for (i=0;i<10;i++)
	{
		sum += buf[i];
	}

	return sum;
	*/
	//version 2
	jint * carr;
	jint i, len, sum = 0;
	carr = env->GetIntArrayElements(arr,NULL);
	if(carr==NULL)
	{
		return 0;
	}

	len = env->GetArrayLength(arr);

	for (i=0;i<len;i++)
	{
		sum += carr[i];
	}
	env->ReleaseIntArrayElements(arr,carr,NULL);

	return sum;

}


/*
 * Class:     cyper_jni_Test
 * Method:    getString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_cyper_jni_Test_getString
(JNIEnv * env, jobject obj){

	//version 1
	/*
	const wchar_t* str = L"Here is a quite long and useless string. Note that this even works with non-ASCII characters, like in ";
	size_t len = wcslen(str);
	if (sizeof(wchar_t) != sizeof(jchar)) {
		printf("this is linux
"); // In Linux, we get there. // First, allocate a buffer for the string to pass to Java, not forgetting the \0 jchar* str2 = (jchar*)malloc((len+1)*sizeof(jchar)); int i; for (i = 0; i < len; i++) // This discards two bytes in str[i], but these should be 0 in UTF-16 str2[i] = str[i]; str2[len] = 0; // Now we have a compatible string! jstring js = env->NewString(str2, len); // And we can free the buffer, to prevent memory leaks free(str2); return js; } else { printf("this is windows
"); // Under Windows, we don't need such a hack return env->NewString((const jchar *)str, len); }*/ //version 2 std::wstring wstr(L"hello "); //NewString unicode jchar *, wstring wchar_t * const wchar_t * pwchar = const_cast<wchar_t*>(wstr.c_str()); return env->NewString((const jchar *)pwchar,wcslen(pwchar)); } /* * Class: cyper_jni_Test * Method: initInt2DArray * Signature: (I)[[I */ JNIEXPORT jobjectArray JNICALL Java_cyper_jni_Test_initInt2DArray (JNIEnv * env, jclass cls, jint size) { jobjectArray result; int i; jclass intArrCls = env->FindClass("[I"); if(intArrCls == NULL) { return NULL; } result = env->NewObjectArray(size,intArrCls,NULL); if (result == NULL) { return NULL; } for (i=0; i<size; i++) { jint tmp[256]; //make sure it is large enough,Cyper:I think the same with size is enough! int j; jintArray iarr = env->NewIntArray(size); if(iarr == NULL){ return NULL; } for (j=0; j<size; j++) { tmp[j] = i+j; } env->SetIntArrayRegion(iarr,0,size,tmp); env->SetObjectArrayElement(result,i,iarr); env->DeleteLocalRef(iarr); } return result; } /* * Class: cyper_jni_Test * Method: getStringArray * Signature: ()[Ljava/lang/String; */ JNIEXPORT jobjectArray JNICALL Java_cyper_jni_Test_getStringArray (JNIEnv * env, jobject obj){ const wchar_t* str1 = L"hello 1"; const wchar_t* str2 = L"hello 2"; const wchar_t* str3 = L"hello 3"; std::vector<const wchar_t*> v; v.push_back(str1); v.push_back(str2); v.push_back(str3); // String jclass strCls = env->FindClass("java/lang/String"); if(strCls == NULL) { return NULL; } // 3 String jobjectArray result = env->NewObjectArray(3,strCls,NULL); if (result == NULL) { return NULL; } // for (int i=0; i<v.size();i++) { jobject jstr = env->NewString((const jchar *)v[i],wcslen(v[i])); env->SetObjectArrayElement(result,i,jstr); } return result; }

出力:helloオープンソース中国550 1 2 2 3 3 4 helloオープンソース中国1 helloオープンソース中国2 helloオープンソース中国3
参照先:http://yaojingguo.iteye.com/blog/542383
参照先:http://www.linuxidc.com/Linux/2012-05/60870.htm 
参照先:http://stackoverflow.com/questions/6504544/passing-array-of-strings-from-c-file-to-java-dll-via-jni/6506390#6506390