在Java中调用C++和C++中回调Java


在Java中调用C++


在java中定义类

package com.example.test;

public class CDevice {
    public  int nMode;
    public float nTemp;
}

java中定义native函数setDevice

package com.example.test;

public class DeviceFun {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("test");
    }

    public native static int setDevice(CDevice device);
    public native static int getDevice(CDevice device);
}

 此时,函数名setDevice是红色,把鼠标在函数名上悬浮片刻,在弹出的提示框中选择“Create JNI function for test",选择cpp文件,生成函数,添加函数内容即可

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_test_DeviceFun_setDevice(JNIEnv *env, jclass clazz, jobject device) {
    jclass objectClass = env->FindClass("com/example/test/CDevice");
    if (objectClass == NULL)
    {
        return -1;
    }

    jfieldID jMode = env->GetFieldID(objectClass, "nMode", "I");
    jfieldID jTemp = env->GetFieldID(objectClass, "nTemp", "F");


    if (device == NULL)
    {
        return -1;
    }

    int nMode;
    if (jMode != NULL)
    {
        nMode = env->GetIntField(device, jMode);
    }

    float nTemp;
    if (jTemp != NULL)
    {
        nTemp = env->GetFloatField(device, jTemp);
    }

    //c++接口:setDevice(nMode, nTemp);
    env->DeleteLocalRef(objectClass);
    return 0;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_test_DeviceFun_getDevice(JNIEnv *env, jclass clazz, jobject device) {
    jclass objectClass = env->FindClass("com/example/test/CDevice");
    if (objectClass == NULL)
    {
        return -1;
    }

    jfieldID jMode = env->GetFieldID(objectClass, "nMode", "I");
    jfieldID jTemp = env->GetFieldID(objectClass, "nTemp", "F");


    if (device == NULL)
    {
        return -1;
    }

    int nMode;
    float nTemp;
    //c++接口:getDevice(nMode, nTemp);

    if (jMode != NULL)
    {
        env->SetIntField(device, jMode, nMode);
    }

    if (jTemp != NULL)
    {
        env->SetFloatField(device, jTemp, nTemp);
    }

    env->DeleteLocalRef(objectClass);
    return 0;
}

在C++中回调Java


JNI提供了两个特殊函数JNI_OnLoad()和JNI_OnUnload(),分别在加载库和卸载库的时候调用。

可在c++的JNI_OnLoad()中将JavaVM参数保存为全局对象,方便在任何地方获取JNIEnv对象

#include <jni.h>
JavaVM *g_jvm;

jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
    g_jvm = vm;//获取一个全局的VM指针
    JNIEnv *env = NULL;
    //通过JavaVM获取JNIEnv,成功后返回JNI_OK
    jint result = vm->GetEnv((void **) &env, JNI_VERSION_1_4);
    if (result != JNI_OK || env == NULL)
    {
        return -1;
    }
    // 返回jni的版本
    return JNI_VERSION_1_4;
}

在java中定义回调的接口

public interface INotify
{
    void notifyTemp(float nTemp);
}

在java中定义native接口将INotify接口传给c++

public native static int init(INotify notify);

c++中实现native接口init

jobject g_jobj;
jmethodID jmid_notifyTemp;

extern "C"
 jint 
Java_com_example_test_DeviceFun_init(JNIEnv *env, jclass clazz,
                                                   jobject notify)
{
    if (g_jobj == NULL)
    {
        g_jobj = env->NewGlobalRef(notify);
    }
    env->GetJavaVM(&g_jvm);//JNI_OnLoad保存的全局变量

    jclass clz = env->GetObjectClass(g_jobj);
    if (clz)
    {
        jmid_notifyTemp = env->GetMethodID(clz, "notifyTemp", "(F)V");
    }
}

c++中的回调函数定义如下

void notifyTemp(float nTemp)
{
    JNIEnv *env;
    bool isAttached = isAttachedCurrentThread(&env);

    if (NULL != env)
    {
        env->CallVoidMethod(g_jobj, jmid_notifyTemp, nTemp);
    }

    //可能从C++主动调用
    //可能从java调用到c++再调用回java    
    //所以加该判断
    if (isAttached)
    {
        r_vm->DetachCurrentThread();
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值