环境:win7 64, vs2008,eclipse3.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\n"); // 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\n"); // 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开源中国
55
0 1 2 1 2 3 2 3 4
hello开源中国1
hello开源中国2
hello开源中国3