jni 自定义对象为参数和返回值

来源:互联网 发布:java 延时队列 编辑:程序博客网 时间:2024/04/29 01:50


 android JNI 提供了很强大的支持,不仅可以采用基本类型做为参数和返回值,同时也支持自定义对象做为参数和返回值,以下举例说明。

一、定义作为输入和返回的自定义类 (仅提供两个简单类型和一个打印函数)

[java] view plaincopy
  1. package com.example.jniexample;  
  2.   
  3. import android.util.Log;  
  4.   
  5. public class JNIParam {  
  6.     public int mInt;  
  7.     public String mString;  
  8.       
  9.     JNIParam(){  
  10.         mInt    = 0;  
  11.         mString = "0";   
  12.     }  
  13.       
  14.     public void print(String tag){  
  15.         Log.d(tag, String.format("print: mInt=%d, mString=%s", mInt, mString));  
  16.     }  
  17. }  

二. 定义和JNI通信的java封装 

功能:测试输入参数和返回值都为自定义对象的本地方法,同时提供必要的调试打印

[java] view plaincopy
  1. package com.example.jniexample;  
  2.   
  3. public class JNIParamTest {  
  4.     private final String TAG = "JNIParamTest";  
  5.       
  6.     static {  
  7.         System.loadLibrary("JNIParamTest");  
  8.     };  
  9.   
  10.     public void runParamTest(){  
  11.         JNIParam paramIn = new JNIParam();  
  12.         paramIn.print(TAG);  
  13.           
  14.         JNIParam paramOut = doTest(paramIn);  
  15.         if( paramOut != null ) paramOut.print(TAG);  
  16.     }  
  17.       
  18.     //JNI  
  19.     private native JNIParam doTest(JNIParam paramIn);  
  20. }  

三、实现JNI的本地实现

a. 头文件 (JNIParamTest.h)

[cpp] view plaincopy
  1. /* DO NOT EDIT THIS FILE - it is machine generated */  
  2. #include <jni.h>  
  3. /* Header for class com_example_jniexample_JNIParamTest */  
  4.   
  5. #ifndef _Included_com_example_jniexample_JNIParamTest  
  6. #define _Included_com_example_jniexample_JNIParamTest  
  7. #ifdef __cplusplus  
  8. extern "C" {  
  9. #endif  
  10. /* 
  11.  * Class:     com_example_jniexample_JNIParamTest 
  12.  * Method:    doTest 
  13.  * Signature: (Lcom/example/jniexample/JNIParam;)Lcom/example/jniexample/JNIParam; 
  14.  */  
  15. JNIEXPORT jobject JNICALL Java_com_example_jniexample_JNIParamTest_doTest  
  16.   (JNIEnv *, jobject, jobject);  
  17.   
  18. #ifdef __cplusplus  
  19. }  
  20. #endif  
  21. #endif  

b. c文件 (JNIParamTest.c)

[cpp] view plaincopy
  1. #include "JNIParamTest.h"  
  2.   
  3. #include "android/log.h"  
  4. #define TAG  "JNI_ParamTest"  
  5. #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)  
  6.   
  7. /* 
  8.  * Class:     com_example_jniexample_JNIParamTest 
  9.  * Method:    doTest 
  10.  * Signature: (Lcom/example/jniexample/JNIParam;)Lcom/example/jniexample/JNIParam; 
  11.  */  
  12. JNIEXPORT jobject JNICALL Java_com_example_jniexample_JNIParamTest_doTest  
  13.   (JNIEnv *env, jobject thiz, jobject paramIn)  
  14. {  
  15.     jclass paramInClass = (*env)->GetObjectClass(env, paramIn);  
  16.     if( paramInClass){  
  17.         jboolean iscopy;  
  18.         jfieldID intId = (*env)->GetFieldID(env, paramInClass, "mInt""I");  
  19.         jint num = (int)(*env)->GetIntField(env, paramIn, intId);  
  20.         LOGD("num = %d", num);  
  21.   
  22.         jfieldID strId = (*env)->GetFieldID(env, paramInClass, "mString""Ljava/lang/String;");  
  23.         jstring str = (jstring)(*env)->GetObjectField(env, paramIn, strId);  
  24.         const char *locstr = (*env)->GetStringUTFChars(env, str, &iscopy);  
  25.         LOGD("str = %s", locstr);  
  26.   
  27.         (*env)->ReleaseStringUTFChars(env, str, locstr);  
  28.     }  
  29.   
  30.     jclass cls = (*env)->FindClass(env, "com/example/jniexample/JNIParam");  
  31.     jmethodID id = (*env)->GetMethodID(env, cls, "<init>""()V");  
  32.   
  33.     jobject paramOut = (*env)->NewObjectA(env, cls, id, 0);  
  34.   
  35.     jfieldID  intId = (*env)->GetFieldID(env, cls, "mInt""I");  
  36.     (*env)->SetIntField(env, paramOut, intId, 1);  
  37.       
  38.     jfieldID  strId = (*env)->GetFieldID(env, cls, "mString""Ljava/lang/String;");  
  39.     (*env)->SetObjectField(env, paramOut, strId, (jstring)(*env)->NewStringUTF(env, "1"));  
  40.   
  41.     return paramOut;  
  42. }  


四、提供一个测试环境

[java] view plaincopy
  1. package com.example.jniexample;  
  2.   
  3. import android.os.Bundle;  
  4. import android.app.Activity;  
  5. import android.view.Menu;  
  6.   
  7. public class JNIExample extends Activity {  
  8.   
  9.     @Override  
  10.     public void onCreate(Bundle savedInstanceState) {  
  11.         super.onCreate(savedInstanceState);  
  12.         setContentView(R.layout.activity_jniexample);  
  13.           
  14.         JNIParamTest test = new JNIParamTest();  
  15.         test.runParamTest();  
  16.     }  
  17.   
  18.     @Override  
  19.     public boolean onCreateOptionsMenu(Menu menu) {  
  20.         getMenuInflater().inflate(R.menu.activity_jniexample, menu);  
  21.         return true;  
  22.     }  
  23. }  

实现了一个Activity, 启动就调用


五、测试结果: (logcat 查看)

[java] view plaincopy
  1. D/JNIParamTest( 6135): print: mInt=0, mString=0  
  2. D/JNI_ParamTest( 6135): num = 0  
  3. D/JNI_ParamTest( 6135): str = 0  
  4. D/JNIParamTest( 6135): print: mInt=1, mString=1  


六、其他类型转换可以参考:

http://blog.csdn.net/henry121212/article/details/7482527   

0 0
原创粉丝点击