zoukankan      html  css  js  c++  java
  • android JNI 资料大全

    1. JNIEnv对象 

     

      对于本地函数
       JNIEXPORT void JNICALL Java_video1_TestNative_sayHello(JNIEnv * env, jobject obj)
       {  
          cout<<"Hello Native Test !"<<endl;  
       }  
       
          JNIEnv类型代表Java环境。

    通过这个JNIEnv*指针,就能够对Java端的代码进行操作。如,创建Java类得对象,调用Java对象的方法,获取Java对象的属性等。

         JNIEnv的指针会被JNI传送到本地方法的实现函数中来对Java端的代码进行操作

     

         
         JNIEnv类中的函数:
         NewObject/NewString/New<TYPE>Array  :new新对象
         Get/Set<TYPE>Field:获取属性
         Get/SetStatic<TYPE>Field :获取静态属性
         Call<TYPE>Method/CallStatic<TYPE>Method:调用方法
         
    2. Java数据类型与C/C++数据类型的相应关系

     

     能够參考 jni.h 文件:http://home.pacifier.com/~mmead/jni/cs510ajp/jni.h
     
    复制代码
    Java类型      别名             C++本地类型          字节(bit)  
    boolean      jboolean            unsigned char      8, unsigned  
    byte         jbyte               signed char       8  
    char         jchar               unsigned short     16, unsigned  
    short        jshort              short               16  
    int          jint                long               32  
    long         jlong               __int64         64  
    float        jfloat              float           32  
    double       jdouble             double              64  
    void         void                                   n/a   
    复制代码

    Object        _jobject            *jobject    

     

     
    3. 获取jclass

     

        为了可以在C/C++使用Java类。jni.h头文件里专门定义了jclass类型来表示Java中的Class类
        jclass的取得:
        JNIEnv类中有例如以下几个简单的函数能够取得jclass
        jclass FindClass(const char* clsName)  依据类名来查找一个类,完整类名。
        jclass GetObjectClass(jobject obj)   依据一个对象,获取该对象的类
        jclass GetSuperClass(jclass obj)     获取一个类的父类
        
        FindClass 会在classpath系统环境变量下寻找类,须要传入完整的类名,注意包与包之间是用"/"而不是"."来切割
    如:jclass cls_string= env->FindClass("java/lang/String");
     
    获取jclass又什么用,比方你要调用类的静态方法,静态属性就须要通过这种方法来获取一个类。

     

     
    4. 本地代码訪问Java类中的属性与方法 

     

     
    有了类和对象之后。怎样才干訪问java中的对象的属性和方法呢,这就须要用到下面这些方法了。
     JNI在jni.h头文件里定义了jfieldID。jmethodID类表示Java端的属性和方法
    怎样获取属性: 在訪问或设置Java属性的时候,首先就要如今本地代码中取得代表Java属性的jfieldID。然后才干在本地代码中进行Java属性操作。
    怎样调用java的方法:调用Java端的方法时,须要取得代表方法的jmethodID才干进行Java方法调用
     
    JNIEnv获取对应的fieldID和jmethodID的方法:
        GetFieldID/GetMethodID
        GetStaticFieldID/GetStaticMethodID
        GetMethodID也能够取得构造函数的jmethodID。

    创建Java对象时调用指定的构造函数。

        如:env->GetMethodID(data_Clazz,"method_name","()V")
        (*jniEnv)->GetMethodID(jniEnv, Clazz,"<init>", "()V"); 
        这个比較特殊。这个是默认构造函数的方法,一般用这个来初始化对象,可是再实际过程中,为了高速生成一个实例,一般通过工厂方法类创建jobject
        
        jni.h 对GetMethodID的定义:
        jmethodID (JNICALL *GetMethodID)
          (JNIEnv *env, jclass clazz, const char *name, const char *sig);
          
        这就引入了一个新的问题。什么是sig,我们后面再说。举个样例说明
        前提说明: JAVA类 TestProvider ,该类有2个方法分别为String getTime( ) , void saysayHello( String str)
        
    jclass TestProvider;
    jobject mTestProvider;
    jmethodID getTime;
    jmethodID sayHello;
     
    C 中映射类   
    TestProvider = (*jniEnv)->FindClass(jniEnv,"com/duicky/TestProvider");

    C中新建对象    

          //默认构造函数。不传參数
           jmethodID construction_id = (*jniEnv)->GetMethodID(jniEnv, TestProvider,"<init>""()V");
           //通过NewObject来创建对象
           jobject mTestProvider = (*jniEnv)->NewObject(jniEnv, TestProvider,construction_id);
    C 中映射方法 
           静态:
    getTime = (*jniEnv)->GetStaticMethodID(jniEnv, TestProvider, "getTime","()Ljava/lang/String;");
           非静态:
    sayHello = (*jniEnv)->GetMethodID(jniEnv, TestProvider, "sayHello","(Ljava/lang/String;)V");
    C 中调用 Java的 方法
           静态:
    (*jniEnv)->CallStaticObjectMethod(jniEnv, TestProvider, getTime);
           非静态:
    (*jniEnv)->CallVoidMethod(jniEnv, mTestProvider, sayHello,jstrMSG);
     
    注意 GetXXXMethodID  和 CallXXXMethod 。
    第一个XXX 表示的是映射方法的类型,如: 静态 跟非静态
    第二个 XXX 表示 调用方法的返回值 ,如:Void,Object,等等。(调用静态方法的时候Call后面要加Static)
        
      5. sign签名
        对于 jmethodID GetMethodID(jclass clazz, const char *name, const char *sign)
        clazz代表该属性所在的类,name表示方法名称,sign是签名
        那什么是签名。签名是对函数參数和返回值的描写叙述,对同一个函数。在java中同意重载。这个时候就须要这个sign来进行区分了。
        下面是java类型签名的描写叙述
        
    用来表示要取得的属性/方法的类型  

     

    复制代码
    类型           对应的签名  
    boolean        Z  
    byte           B  
    char           C  
    short          S  
    int            I  
    long           J  
    float          F  
    double         D  
    void           V  
    object         L用/分隔包的完整类名:   Ljava/lang/String; 
    Array          [签名          [I      [Ljava/lang/Object;  
    Method         (參数1类型签名 參数2类型签名···)返回值类型签名  
    复制代码


     
    特别注意:Object后面一定有分号(。)结束的,多个对象參数中间也用分号(;)来分隔

     

     
    样例:
    方法签名
    void f1()                         ()V
    int f2(intlong)                 (IJ)I
    boolean f3(int[])                 ([I)B
    double f4(String, int)            (Ljava/lang/String;I)D
    void f5(int, String [], char)    (I[Ljava/lang/String;C)V
     
     

     图解签名:

     

     

     
    使用javap命令来产生签名
         javap -s -p [full class Name]
         -s 表示输出签名信息
         -p 同-private,输出包含private訪问权限的成员信息
       
     样例:
    复制代码
     C:EjavaworkspacesmyeclipseblueJNITestin>javap -s -private video1.TestNative  
    Compiled from "TestNative.java"  
    public class video1.TestNative extends java.lang.Object{  
    public java.lang.String name;  
      Signature: Ljava/lang/String;  
    public video1.TestNative();  
      Signature: ()V  
    public int signTest(int, java.util.Date, int[]);  
      Signature: (ILjava/util/Date;[I)I  
    public native void sayHello();  
      Signature: ()V  
    public static void main(java.lang.String[]);  
      Signature: ([Ljava/lang/String;)V  
    }   
    复制代码
     
     

    TestNative完整代码:

     
    复制代码
    package video1;  
    import java.util.Date;  
    public class TestNative {  
        public String name="Test";  
        public int number =100;  
        public int signTest(int i,Date date,int[] arr){  
            System.out.println("Sign Test");  
            return 0;  
        }  
        //nativekeyword修饰的方法,其内容是C/C++编写的,java中不必为它编写详细的实现  
        public native void sayHello();  
        public static void main(String[] args) {  
            System.loadLibrary("NativeCode");  
            TestNative tn = new TestNative();  
            tn.sayHello();  
        }  
    }
    复制代码
     
     

    C/C++代码

     

     
    复制代码
    #include "video1_TestNative.h"  
    #include <iostream>  
    using namespace std;  
    JNIEXPORT void JNICALL Java_video1_TestNative_sayHello(JNIEnv * env, jobject obj){  
        cout<<"Hello Native Test !"<<endl;  
        //由于test不是静态函数,所以传进来的就是调用这个函数的对象  
        
    //否则就传入一个jclass对象表示native()方法所在的类  
        jclass native_clazz = env->GetObjectClass(obj);  
      
        //得到jfieldID  
        jfieldID fieldID_prop = env->GetFieldID(native_clazz,"name","Ljava/lang/String;");  
        jfieldID fieldID_num = env->GetFieldID(native_clazz,"number","I");  
      
        //得到jmethodID  
        jmethodID methodID_func=env->GetMethodID(native_clazz,"signTest","(ILjava/util/Date;[I)I");  
        //调用signTest方法  
        env->CallIntMethod(obj,methodID_func,1L,NULL,NULL);  
      
        //得到name属性  
        jobject name = env->GetObjectField(obj,fieldID_name);  
        //得到number属性  
        jint number= env->GetIntField(obj,fieldID_num);   
      
        cout<<number<<endl;//100  
        
    //改动number属性的值  
        env->SetIntField(obj,fieldID_num,18880L);    
        number= env->GetIntField(obj,fieldID_num);    
        cout<<number<<endl;//18880  
     }  
    复制代码
     

    本文地址,转载请注明出处:

    http://www.cnblogs.com/likwo/archive/2012/05/21/2512400.html 

     

    參考资料:

     

     
    jni.h 头文件:

     

    相关样例:

     

    Programmming in C/C++ with the Java Native Interface (3 个练习)

     

     
    JNI 文档:

     

     
    基于 Android NDK 的学习之旅----- C调用Java

     

     
    Linux下JNI的使用:比較基础

     

     
    怎样在Android下使用JNI:解说比較具体,可是代码里有些错误,空格没处理好
    这篇文章有些地方不清楚的參考下这篇文章
     
    Android Jni代码演示样例解说

     

    JNI callMethod參考文档

     

    其它推荐学习站点

     

    JNI的提高,Java类型和C(C++)类型转换源码

    http://blog.csdn.net/ostrichmyself/article/details/4557851 

     

    JNI 的多线程

     http://blog.csdn.net/popop123/article/details/1511180 

     

    Android NDK 开发 

     

     

    使用 Java Native Interface 的最佳实践:描写叙述了JNI性能和缓存的一些东西

     

     https://www.ibm.com/developerworks/cn/java/j-jni/

     

    JNI 攻略系列

    JNI全攻略之中的一个--建立一个简单的JNI程序 

    http://blog.csdn.net/yjkwf/article/details/7006260 

    JNI全攻略之二――JNI基础 

    http://blog.csdn.net/yjkwf/article/details/7006261 

     JNI全攻略之三--JNI头文件分析

     http://blog.csdn.net/yjkwf/article/details/7006264

     JNI攻略之四――JNI操作数组

    http://blog.csdn.net/yjkwf/article/details/7006266 

     

    http://disanji.net/2011/01/26/android-jni-programming-2/ 

     

     JNI Examples for Android

    http://android.wooyd.org/JNIExample/files/JNIExample.pdf 

     

    JNI pthread 多线程使用

    http://www.cnblogs.com/lknlfy/archive/2012/03/16/2400786.html 

     

     

  • 相关阅读:
    rs
    stm32f767 usoc3
    stm32f767 RTT 日志
    stm32f767 标准库 工程模板
    stm32f767 HAL 工程模板
    docker tab 补全 linux tab 补全
    docker anconda 依赖 下载 不了
    docker run 常用 指令
    linux scp 命令
    Dockerfile 常用参数说明
  • 原文地址:https://www.cnblogs.com/mthoutai/p/6872983.html
Copyright © 2011-2022 走看看