二、C++访问Java代码-知识点

第二讲主要是介绍JNI中提供的调用和修改以及其他一些操作java代码的方法,具体如下

1、Java工具生成的C/C++函数声明中,可以看到两个参数:

//对 com_fomagic_TestNative.h 中声明的方法定义
JNIEXPORT void JNICALL Java_com_fomagic_TestNative_sayHello (JNIEnv *evn, jobject obj)
{
    cout<<"Hello World !"<<endl;
}

JNIEnv *env

JNIEnv类型可以看做是Java环境,通过这个JNIEnv* 指针,可以对Java端的代码进行操作,

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

例如:创建Java类的对象,调用Java对象的方法,获取Java对象的属性等

<TYPE> 代表数据类型

函数:NewObject/NewString/New<TYPE>Array        //创建数组

Get/Set<TYPE>Field                 //获取/设定变量属性

Get/SetStatic<TYPE>Method/CallStatic<TYPE>Method  …         //对方法进行操作

我们可以在jni.h 头文件中找到所有定义的方法:

struct JNIEnv_;  //定义所有方法的结构体
typedef JNIEnv_ JNIEnv;
      ………………
 
struct JNIEnv_ {
    const struct JNINativeInterface_ *functions;
      ………………
    jclass FindClass(const char *name) {
        return functions->FindClass(this, name);
    }
      ………………
    jint GetIntField(jobject obj, jfieldID fieldID) {
        return functions->GetIntField(this,obj,fieldID);
    }
}

jobject obj

同样也可以在jni.h中看到对jobject的定义

表示传进来的参数为调用该方法的对象,如果是 静态native函数,则表示native方法坐在的类

2、Java类型在C/C++中的映射关系

这个没有什么要说的,直接看图,就是JNI 为了我方便使用定义的别名

 

JNI_201

3、jclass的取得

      为了可以在C/C++中使用Java类 jni.h头文件中专门定义了jclass类型来表示Java中的Class类

   

      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”);

4、访问Java类中的属性和方法

     在C/C++本地代码中访问Java端的代码,一个常见的应用就是获取类的属性和调

     用类的方法,为了在C/C++中表示属性和方法,JNI在jni.h 头文件中定义了

     jfieldID、jmethodID 类型来分别代表Java端的属性和方法

     在访问设置Java 属性 和 方法 时,首先在本地代码获取代表Java属性的jfieldID 和jmethodID 然后进行Java属性和方法的操作

     JNIEnv中  GetFieldID/GetMethodID    GetStaticFieldID/GetStaticMethodID 获取

     如:env->GetMethodID(data_Clazz,”<int>”,”()V”);   //  ()V指无返回类型void,下面讲到

 

5、Sign是什么?

例如TestNative.java中有两个重载方法:

package com.fomagic;
public class TestNative {
    public void function(int i){
        System.out.println("Integer: "+i);
    }
    public void function(double d){
        System.out.println("Double: "+d);
    }
}


 

当在C++中调用其中一个函数的时候,就需要按照以下步骤:

    1、获取函数所在类     jclass clazz_Testnative=env->FindClass(“com.fomagic.TestNative”);

2、获取方法的 jmethodID 来调用方法   jmethodID id_func =env->GetMethodID (clazz_Testnative,”function”,” (I)V”);

->GetMethodID (clazz_Testnative,”function”,” (D)V”);

其中 通过指定函数的参数类型和返回值类型 来返回 jmethodID,从而对应的函数,这就是sign

以下是对应类型:

JNI_sign JNI_sign_2

6、使用javap命令生成签名

  JDK中提供了 javap工具来查看类的声明,可以输出每个方法与属性的签名

package com.fomagic;
import java.util.Date;
public class TestNative {
    public native void sayHello(); //C++本地代码实现    
    public static void main(String[] args) {
        System.loadLibrary("NativeCode");//加载动态链接库,不能加 .dll         
        TestNative test=new TestNative();    
        test.sayHello();
    }
    
    public int property;
    public int function(int foo,Date date, int[] arr){
        
        return 0;
    }
}


我们对上面代码通过 javap 工具直接生成方法和属性的签名:

1、命令行定位到该类的绝对路径  cd TestNativeCode\bin 目录

2、执行 javap -s -private com.fomagic.Testnative

javap -s  -p…  [完整类名]

注:private获取全部权限的成员、public获取public修饰的成员 (即 获取大于或等于自己权限的成员方法或属性)

 JNI_javap01    JNI_javap02


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值