转JNI 对象处理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了转JNI 对象处理相关的知识,希望对你有一定的参考价值。

原文网址:http://leidiqiu.iteye.com/blog/720307

JNI 的基本问题就是解决 Java 和 C++ 代码互相调用的通信问题,在 C++ 代码编写过程中最大的问题莫过于适应其中的代码编写规则,C++调用或是返回的内容必须遵守 JVM 和 C++ 代码的通信规则。

C++ 调用 Java 的一般步骤如下:

  • 获得类:
    • jclass cls          = env->FindClass("com/ldq/Student");
    • cls 可认为是类的句柄
    • "com/ldq/Student" 就是类文件,注意不能用 "com.ldq.Student"
  • 获得方法:
    • jmethodID mid = env->GetMethodID(cls,"<init>","()V");
    • 以上为构造函数,参数是 "<init>" "()V"
    • jmethodID mid = env->GetMethodID(cls,"getAge","()I");
    • 以上为类的方法,第一个参数是类句柄,第二个参数是方法名字,第三个参数是签名标识 

Java类型

符号
boolean

byte

char

C  
short
int
long L  
float F  

double

D  

void

objects对象 Lfully-qualified-class-name;        L类名;
Arrays数组 [array-type [数组类型 
methods方法                  (argument-types)return-type(参数类型)返回类型 
  • 获得对象:
    • jobject obj=env->NewObject(cls,mid);
    • 以上便获得了一个对象的句柄
  • 获得对象成员变量:
    • jfieldID fid=env->GetFieldID(cls,"age","I");
    • 以上和获得类方法差不多
  • 操作成员变量:
    • jint a=env->GetIntField(obj,mid);
    • age=age+10;
    • env->SetIntField(obj,fid,a);
  • 返回:
    • return obj;

下面是本人练习的例子

  • ExList.java

 

Java代码  
  1. package com.ldq.list;  
  2.   
  3. import java.util.List;  
  4.   
  5. public class ExList {  
  6.   
  7.     /** 
  8.      * @param args 
  9.      */  
  10.     public static void main(String[] args) {  
  11.         // TODO Auto-generated method stub  
  12.         System.out.println("-------WifiManager.test()");  
  13.         System.out.println(WifiManager.test());  
  14.   
  15.         System.out.println("-------WifiManager.testArray()");  
  16.         String[] s1 = WifiManager.testArray();  
  17.         for (int i = 0; i < s1.length; i++) {  
  18.             System.out.println(s1[i]);  
  19.         }  
  20.   
  21.         System.out.println("-------WifiManager.testObject()");  
  22.         System.out.println(WifiManager.testObject().ssid);  
  23.         System.out.println(WifiManager.testObject().mac);  
  24.         System.out.println(WifiManager.testObject().level);  
  25.   
  26.         System.out.println("-------WifiManager.getScanResultsA()");  
  27.         ScanResult[] s2 = WifiManager.getScanResultsA();  
  28.         for (int i = 0; i < s2.length; i++) {  
  29.             System.out.println(s2[i].ssid);  
  30.             System.out.println(s2[i].mac);  
  31.             System.out.println(s2[i].level);  
  32.         }  
  33.   
  34.         System.out.println("-------WifiManager.getScanResults()");  
  35.         List<ScanResult> list = WifiManager.getScanResults();  
  36.         System.out.println(list.get(0).ssid);  
  37.         System.out.println(list.get(0).mac);  
  38.         System.out.println(list.get(0).level);  
  39.   
  40.     }  
  41. }  

 

 

 

 

  • ScanResult.java

 

Java代码  
  1. package com.ldq.list;  
  2.   
  3. public class ScanResult {  
  4.     String ssid;  
  5.     String mac;  
  6.     int level;  
  7.   
  8.     public ScanResult() {  
  9.     }  
  10.   
  11.     public ScanResult(String ssid, String mac, int level) {  
  12.         this.ssid = ssid;  
  13.         this.mac = mac;  
  14.         this.level = level;  
  15.     }  
  16. }  

 

 

 

 

  • WifiManager.java

 

Java代码  
  1. package com.ldq.list;  
  2.   
  3. import java.util.List;  
  4.   
  5. public class WifiManager {  
  6.   
  7.     static {  
  8.         System.loadLibrary("wifi");  
  9.     }  
  10.   
  11.     public native static String test();  
  12.   
  13.     public native static String[] testArray();  
  14.   
  15.     public native static ScanResult testObject();  
  16.   
  17.     public native static ScanResult[] getScanResultsA();  
  18.   
  19.     public native static List<ScanResult> getScanResults();  
  20. }  

 

  • wifi.cpp
Cpp代码  
  1. #include <jni.h>  
  2. #include "com_ldq_list_WifiManager.h"  
  3.   
  4. /* 
  5.  * Class:     com_ldq_list_WifiManager 
  6.  * Method:    test 
  7.  * Signature: ()Ljava/lang/String; 
  8.  */  
  9. JNIEXPORT jstring JNICALL Java_com_ldq_list_WifiManager_test (JNIEnv *env, jclass cls)  
  10. {  
  11.     return env->NewStringUTF("hello");  
  12. }  
  13.   
  14. /* 
  15.  * Class:     com_ldq_list_WifiManager 
  16.  * Method:    testArray 
  17.  * Signature: ()[Ljava/lang/String; 
  18.  */  
  19. JNIEXPORT jobjectArray JNICALL Java_com_ldq_list_WifiManager_testArray (JNIEnv *env, jclass cls)  
  20. {  
  21.     jobjectArray ret;  
  22.     int i;  
  23.   
  24.     char *message[5]= {"first",   
  25.     "second",   
  26.     "third",   
  27.     "fourth",   
  28.     "fifth"};  
  29.   
  30.     ret= (jobjectArray)env->NewObjectArray(5,  
  31.          env->FindClass("java/lang/String"),  
  32.          env->NewStringUTF(""));  
  33.   
  34.     for(i=0;i<5;i++) {  
  35.         env->SetObjectArrayElement(  
  36.         ret,i,env->NewStringUTF(message[i]));  
  37.     }  
  38.     return(ret);  
  39.   
  40. }  
  41.   
  42. /* 
  43.  * Class:     com_ldq_list_WifiManager 
  44.  * Method:    testObject 
  45.  * Signature: ()Lcom/ldq/list/ScanResult; 
  46.  */  
  47. JNIEXPORT jobject JNICALL Java_com_ldq_list_WifiManager_testObject (JNIEnv *env, jclass cls)  
  48. {  
  49.     jclass m_cls  = env->FindClass("com/ldq/list/ScanResult");  
  50.     jmethodID mid = env->GetMethodID(m_cls,"<init>","()V");  
  51.     jobject obj   = env->NewObject(m_cls,mid);  
  52.   
  53.     jfieldID fid_ssid  = env->GetFieldID(m_cls,"ssid","Ljava/lang/String;");  
  54.     jfieldID fid_mac   = env->GetFieldID(m_cls,"mac","Ljava/lang/String;");  
  55.     jfieldID fid_level = env->GetFieldID(m_cls,"level","I");  
  56.   
  57.                          env->SetObjectField(obj,fid_ssid,env->NewStringUTF("AP1"));  
  58.                          env->SetObjectField(obj,fid_mac,env->NewStringUTF("00-11-22-33-44-55"));  
  59.                          env->SetIntField(obj,fid_level,-66);  
  60.     return obj;  
  61. }  
  62.   
  63. /* 
  64.  * Class:     com_ldq_list_WifiManager 
  65.  * Method:    getScanResultsA 
  66.  * Signature: ()[Lcom/ldq/list/ScanResult; 
  67.  */  
  68. JNIEXPORT jobjectArray JNICALL Java_com_ldq_list_WifiManager_getScanResultsA (JNIEnv *env, jclass cls)  
  69. {  
  70.     jclass cls_array=env->FindClass("java/lang/Object");  
  71.     jobjectArray obj_array=env->NewObjectArray(2,cls_array,0);  
  72.   
  73.     jclass cls_obj = env->FindClass("com/ldq/list/ScanResult");  
  74.     jmethodID m    = env->GetMethodID(cls_obj,"<init>","()V");  
  75.   
  76.     jfieldID fid_ssid  = env->GetFieldID(cls_obj,"ssid","Ljava/lang/String;");  
  77.     jfieldID fid_mac   = env->GetFieldID(cls_obj,"mac","Ljava/lang/String;");  
  78.     jfieldID fid_level = env->GetFieldID(cls_obj,"level","I");  
  79.   
  80.     for(int i=0;i<2;i++)  
  81.     {  
  82.         jobject obj=env->NewObject(cls_obj,m);  
  83.   
  84.         jobject o1=env->NewStringUTF("AP2");  
  85.         env->SetObjectField(obj,fid_ssid,o1);  
  86.   
  87.         jobject o2=env->NewStringUTF("22-22-22-22-22-22");  
  88.         env->SetObjectField(obj,fid_mac,o2);  
  89.   
  90.         env->SetIntField(obj,fid_level,-66);  
  91.   
  92.         env->SetObjectArrayElement(obj_array,i,obj);  
  93.     }  
  94.     return obj_array;  
  95. }  
  96.   
  97. /* 
  98.  * Class:     com_ldq_list_WifiManager 
  99.  * Method:    getScanResults 
  100.  * Signature: ()Ljava/util/List; 
  101.  */  
  102. JNIEXPORT jobject JNICALL Java_com_ldq_list_WifiManager_getScanResults (JNIEnv *env, jclass cls)  
  103. {  
  104.     jclass m_cls_list    = env->FindClass("java/util/ArrayList");  
  105.     jmethodID m_mid_list = env->GetMethodID(m_cls_list,"<init>","()V");  
  106.     jobject m_obj_list   = env->NewObject(m_cls_list,m_mid_list);  
  107.   
  108.     jmethodID m_mid_add  = env->GetMethodID(m_cls_list,"add","(Ljava/lang/Object;)Z");  
  109.   
  110.     jclass m_cls_result    = env->FindClass("com/ldq/list/ScanResult");  
  111.     jmethodID m_mid_result = env->GetMethodID(m_cls_result,"<init>","()V");  
  112.     jobject m_obj_result   = env->NewObject(m_cls_result,m_mid_result);  
  113.   
  114.     jfieldID m_fid_1 = env->GetFieldID(m_cls_result,"ssid","Ljava/lang/String;");  
  115.     jfieldID m_fid_2 = env->GetFieldID(m_cls_result,"mac","Ljava/lang/String;");  
  116.     jfieldID m_fid_3 = env->GetFieldID(m_cls_result,"level","I");  
  117.   
  118.     env->SetObjectField(m_obj_result,m_fid_1,env->NewStringUTF("AP6"));  
  119.     env->SetObjectField(m_obj_result,m_fid_2,env->NewStringUTF("66-66-66-66-66-66"));  
  120.     env->SetIntField(m_obj_result,m_fid_3,-66);  
  121.   
  122.     env->CallBooleanMethod(m_obj_list,m_mid_add,m_obj_result);  
  123.   
  124.     return m_obj_list;  
  125. }  

以上是关于转JNI 对象处理的主要内容,如果未能解决你的问题,请参考以下文章

JNI/NDK开发指南——访问数组(基本类型数组与对象数组)

jniC++怎么返回java的对象数组

如何通过JNI将java中的对象的地址赋值给c++指针变量

Android JNI浅析Java和Native通信对象的传值和回调

使用 JNI 在 C 中访问 Java 对象中的 Java 对象

Android JNI之JAVA与C++对象建立对称关联(JNI优化设计,确保JNI调用的稳定性)