JNI 对象处理 (转)

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
    package com.ldq.list;
    
    import java.util.List;
    
    public class ExList {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            System.out.println("-------WifiManager.test()");
            System.out.println(WifiManager.test());
    
            System.out.println("-------WifiManager.testArray()");
            String[] s1 = WifiManager.testArray();
            for (int i = 0; i < s1.length; i++) {
                System.out.println(s1[i]);
            }
    
            System.out.println("-------WifiManager.testObject()");
            System.out.println(WifiManager.testObject().ssid);
            System.out.println(WifiManager.testObject().mac);
            System.out.println(WifiManager.testObject().level);
    
            System.out.println("-------WifiManager.getScanResultsA()");
            ScanResult[] s2 = WifiManager.getScanResultsA();
            for (int i = 0; i < s2.length; i++) {
                System.out.println(s2[i].ssid);
                System.out.println(s2[i].mac);
                System.out.println(s2[i].level);
            }
    
            System.out.println("-------WifiManager.getScanResults()");
            List<ScanResult> list = WifiManager.getScanResults();
            System.out.println(list.get(0).ssid);
            System.out.println(list.get(0).mac);
            System.out.println(list.get(0).level);
    
        }
    }
  • ScanResult.java
    package com.ldq.list;
    
    public class ScanResult {
        String ssid;
        String mac;
        int level;
    
        public ScanResult() {
        }
    
        public ScanResult(String ssid, String mac, int level) {
            this.ssid = ssid;
            this.mac = mac;
            this.level = level;
        }
    }
  • WifiManager.java
    package com.ldq.list;
    
    import java.util.List;
    
    public class WifiManager {
    
        static {
            System.loadLibrary("wifi");
        }
    
        public native static String test();
    
        public native static String[] testArray();
    
        public native static ScanResult testObject();
    
        public native static ScanResult[] getScanResultsA();
    
        public native static List<ScanResult> getScanResults();
    }
  • wifi.cpp
    #include <jni.h>
    #include "com_ldq_list_WifiManager.h"
    
    /*
     * Class:     com_ldq_list_WifiManager
     * Method:    test
     * Signature: ()Ljava/lang/String;
     */
    JNIEXPORT jstring JNICALL Java_com_ldq_list_WifiManager_test (JNIEnv *env, jclass cls)
    {
        return env->NewStringUTF("hello");
    }
    
    /*
     * Class:     com_ldq_list_WifiManager
     * Method:    testArray
     * Signature: ()[Ljava/lang/String;
     */
    JNIEXPORT jobjectArray JNICALL Java_com_ldq_list_WifiManager_testArray (JNIEnv *env, jclass cls)
    {
        jobjectArray ret;
        int i;
    
        char *message[5]= {"first", 
        "second", 
        "third", 
        "fourth", 
        "fifth"};
    
        ret= (jobjectArray)env->NewObjectArray(5,
             env->FindClass("java/lang/String"),
             env->NewStringUTF(""));
    
        for(i=0;i<5;i++) {
            env->SetObjectArrayElement(
            ret,i,env->NewStringUTF(message[i]));
        }
        return(ret);
    
    }
    
    /*
     * Class:     com_ldq_list_WifiManager
     * Method:    testObject
     * Signature: ()Lcom/ldq/list/ScanResult;
     */
    JNIEXPORT jobject JNICALL Java_com_ldq_list_WifiManager_testObject (JNIEnv *env, jclass cls)
    {
        jclass m_cls  = env->FindClass("com/ldq/list/ScanResult");
        jmethodID mid = env->GetMethodID(m_cls,"<init>","()V");
        jobject obj   = env->NewObject(m_cls,mid);
    
        jfieldID fid_ssid  = env->GetFieldID(m_cls,"ssid","Ljava/lang/String;");
        jfieldID fid_mac   = env->GetFieldID(m_cls,"mac","Ljava/lang/String;");
        jfieldID fid_level = env->GetFieldID(m_cls,"level","I");
    
                             env->SetObjectField(obj,fid_ssid,env->NewStringUTF("AP1"));
                             env->SetObjectField(obj,fid_mac,env->NewStringUTF("00-11-22-33-44-55"));
                             env->SetIntField(obj,fid_level,-66);
        return obj;
    }
    
    /*
     * Class:     com_ldq_list_WifiManager
     * Method:    getScanResultsA
     * Signature: ()[Lcom/ldq/list/ScanResult;
     */
    JNIEXPORT jobjectArray JNICALL Java_com_ldq_list_WifiManager_getScanResultsA (JNIEnv *env, jclass cls)
    {
        jclass cls_array=env->FindClass("java/lang/Object");
        jobjectArray obj_array=env->NewObjectArray(2,cls_array,0);
    
        jclass cls_obj = env->FindClass("com/ldq/list/ScanResult");
        jmethodID m    = env->GetMethodID(cls_obj,"<init>","()V");
    
        jfieldID fid_ssid  = env->GetFieldID(cls_obj,"ssid","Ljava/lang/String;");
        jfieldID fid_mac   = env->GetFieldID(cls_obj,"mac","Ljava/lang/String;");
        jfieldID fid_level = env->GetFieldID(cls_obj,"level","I");
    
        for(int i=0;i<2;i++)
        {
            jobject obj=env->NewObject(cls_obj,m);
    
            jobject o1=env->NewStringUTF("AP2");
            env->SetObjectField(obj,fid_ssid,o1);
    
            jobject o2=env->NewStringUTF("22-22-22-22-22-22");
            env->SetObjectField(obj,fid_mac,o2);
    
            env->SetIntField(obj,fid_level,-66);
    
            env->SetObjectArrayElement(obj_array,i,obj);
        }
        return obj_array;
    }
    
    /*
     * Class:     com_ldq_list_WifiManager
     * Method:    getScanResults
     * Signature: ()Ljava/util/List;
     */
    JNIEXPORT jobject JNICALL Java_com_ldq_list_WifiManager_getScanResults (JNIEnv *env, jclass cls)
    {
        jclass m_cls_list    = env->FindClass("java/util/ArrayList");
        jmethodID m_mid_list = env->GetMethodID(m_cls_list,"<init>","()V");
        jobject m_obj_list   = env->NewObject(m_cls_list,m_mid_list);
    
        jmethodID m_mid_add  = env->GetMethodID(m_cls_list,"add","(Ljava/lang/Object;)Z");
    
        jclass m_cls_result    = env->FindClass("com/ldq/list/ScanResult");
        jmethodID m_mid_result = env->GetMethodID(m_cls_result,"<init>","()V");
        jobject m_obj_result   = env->NewObject(m_cls_result,m_mid_result);
    
        jfieldID m_fid_1 = env->GetFieldID(m_cls_result,"ssid","Ljava/lang/String;");
        jfieldID m_fid_2 = env->GetFieldID(m_cls_result,"mac","Ljava/lang/String;");
        jfieldID m_fid_3 = env->GetFieldID(m_cls_result,"level","I");
    
        env->SetObjectField(m_obj_result,m_fid_1,env->NewStringUTF("AP6"));
        env->SetObjectField(m_obj_result,m_fid_2,env->NewStringUTF("66-66-66-66-66-66"));
        env->SetIntField(m_obj_result,m_fid_3,-66);
    
        env->CallBooleanMethod(m_obj_list,m_mid_add,m_obj_result);
    
        return m_obj_list;
    }

    转自:http://leidiqiu.iteye.com/blog/720307

posted @ 2016-03-16 12:12  一双拖鞋走天下  阅读(897)  评论(0编辑  收藏  举报