JNI实用技巧

本文介绍了如何在C++中创建Java对象并调用其方法,详细阐述了FindClass、GetMethodID、NewObject等JNI操作。同时,展示了在C++其他线程中回调Java层的方法,包括GetEnv、AttachCurrentThread、CallVoidMethod等步骤,以及如何处理线程附加和解除。内容涵盖了JNI基础知识和多线程回调技术。
摘要由CSDN通过智能技术生成

1、在C++层创建Java对象

在C++中获取到对应的Java对象,并通过setIntField()方法,对width属性进行赋值

//1、根据传入的包名获取到clazz对象(传入参数的为完整包名)
jclass clazz = env -> FindClass("java/util/date")
//2、根据clazz对象我们可以获取到构造方法
jmethodID construcotr = env -> GetMethodId(clazz,"<init>","()V");

//3、根据获取到的构造方法可以获取到对象
jobject obj = env -> NewObject(clazz, construcotr);

//根据clazz对象获取到对应方法
jmethodID getWidthId = env -> GetMethodId(clazz,"getWidth","()I");

//根据clazz对象我们还可以获取到mWidth这个属性
jfieldID widthId = env -> GetFieldID(clazz,"mWidth","I");

//使用setIntField方法对mWidth这个属性赋值
env -> setIntField(obj,widthId,outImage.width());

GetMethodID能够取得构造防范的jmethodID, 如果传入的要取得的方法名称设为“<init>”就能够取得构造方法,构造方法的方法返回值的签名始终为void

java类型和C++字段描述符
java类型字段描述符
booleanZ
byteB
charC
shortS
intI
longL
floatF
doubleD
voidV

2、在C++其它线程里回调到Java层

在C++对应的Native方法中:

//定义全局变量
JavaVM *g_VM;
jobject g_obj;

(在Native方法中)
//javaVM是虚拟机在JNI中的表示,等下其它线程回调到Java层会用到
env -> GetJava(&g_VM);
//生成一个全局引用保留下来,以便回调
//instance 是native方法传入的参数env后面那个参数jobject instance
//注:当native方法为静态方法时,instance代表native方法所属类的对象
//当native方法为非静态方法时,instance代表native方法所属的对象
env -> NewGlobalRef(instance)


(C++其它线程中)
JNIEnv *env;
bool hasAttached;
//获取当前native线程是否被附加到jvm环境中
jint getEnvState = g_VM -> GetEnv((void**)&env, JNI_VERSION_1_6);
//如果没有则主动附加到jvm环境中,获取到env
if(getEnvState<0){
    if(g_VM -> AttachCurrentThread(&env, NULL)!=0){
        return;
    }else{
        hasAttached = true;
    }
}
//通过全局变量g_obj获取到要回调的类
jclass javaClass = env -> GetObjectClass(g_obj);
if(javaClass == 0){
    g_VM -> DetachCurrentThread();
    return;
}
//获取到要回调的方法ID
jmethodID javaCallbackId = env -> GetMethodID(javaClass, "onTestCallback", "(Ljava/lang/String;)v");
if(javaCallbackId == null){
    LOGE("Unable to find Method:onTsetCallback");
    return;
}
//执行回调
//msg.c_str():就是我们要在java中回调打出来的信息
env -> CallVoidMethod(g_obj, javaCallbackId, env->NewStringUTF(msg.c_str()));
//释放当前线程
if(hasAttached){
    g_VM -> DetachCurrentThread();
}
env = null;

Java层对应的方法(同一个类中)

//total:就是C++中回调过来的 msg.c_str()
private void onTestCallback(String total){
    //C++层回调后执行的操作
    Log.e(TAG, total);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值