AndroidJNI 通过C++调用JAVA

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)  依据类名来搜寻3个类,完整类名。

    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头文件中定义了j田野先生ID,jmethodID类表示Java端的属性和方法

何以赢得属性:
在访问或安装Java属性的时候,首先就要以往本土代码中获取代表Java属性的j田野先生ID,然后才能在地面代码中开始展览Java属性操作。

如何调用java的形式:调用Java端的方法时,须求获得代表办法的jmethodID才能展开Java方法调用

 

JNIEnv获取相应的田野ID和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
,该类有三个法子分别为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(int, long)                 (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

 

 

 图解签名:

Java 1 

 

 

采纳javap命令来产生签名

     javap -s -p [full class
Name]

     -s 表示输出签名音信

     -p
同-private,输出包蕴private访问权限的分子音讯

   

 例子:

 C:\E\java\workspaces\myeclipseblue\JNITest\bin>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;  
    }  
    //native关键字修饰的艺术,其内容是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 

 

参考资料:

http://zzqrj.iteye.com/blog/1285262

 

 

jni.h 头文件:

http://home.pacifier.com/~mmead/jni/cs510ajp/jni.h

 

有关例子:

 

http://www.pacifier.com/~mmead/jni/cs510ajp/index.html

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

http://www.pacifier.com/~mmead/jni/cs510ajp/exercises/index.html

 

 

JNI 文档:

http://files.cnblogs.com/luxiaofeng54/JNI_Docs.rar

 

 

据悉 Android NDK 的求学之旅—–
C调用Java

http://www.cnblogs.com/luxiaofeng54/archive/2011/08/17/2142000.html

 

 

Linux下JNI的运用:比较基础

http://www.cnblogs.com/bastard/archive/2012/05/17/2506877.html

 

 

怎么样在Android下使用JNI:讲解相比较详细,可是代码里多少错误,空格没处理好

http://blog.csdn.net/xnwyd/article/details/7086384

那篇小说有个别地点不掌握的参阅下那篇小说

 

Android Jni代码示例讲解

http://developer.51cto.com/art/201001/181355.htm

 

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, 

使用 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 

 

 

 

 

相关文章