jni进阶测试

环境: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

参考: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

你可能感兴趣的:(jni)