JNI Java层对象和C++底层对象关联,使用与"传long指针"不一样的方式

11 篇文章 0 订阅
7 篇文章 0 订阅

JNI Java层对象和C++底层对象关联,使用与”传long指针”不一样的方式

做Android JNI底层开发的时候,经常需要Java类和C++类做相互对应,比如Java层有一个类MyGLView.java,C++层有一个叫做MyGLView.cpp的类与之对应,所以需要一个叫做 MyGLViewJNI.cpp 的jni接口让MyGLView.java和MyGLView.cpp关联起来,这样,MyGLView.java 就能直接操作底层的MyGLView.cpp。

通常有两种方式,让java层关联c++层对象:
1.c++对象new出来后,将指针转成long型返回给java对象持有,java对象每次操作c++对象时,都要传递它持有的c++对象指针(在java时是long类型)到jni接口,然后强转成c++对象。
2.在jni接口,在c++对象new出来后,将对象指针方向写到java对象的long变量,jni接口也保存与之对应的jfieldID,每次java对象操作c++对象时,直接在jni接口的c++里取出c++对象,这就是接下来要讲的方法。

代码和解析如下:

java对象:

public class MyGLView {
    //跟jni接口的gFields.context成映射关系
    private long mNativeContext;
     private static native long init();
    private static native int create(int vWidth, int vHeight);
    ……
}  
//java对象包名
static const std::string className = "cn/hongda/opengl/opengles/MyGLView";

struct fields_t {
    jfieldID context;
};

//保存C++对象指针,跟上面的java对象的mNativeContext成映射关系
static struct fields_t gFields;

//将java对象的mNativeContext和jni的gFields.context形成映射关系,在jni读写gFields.context,就相当于直接读写java对象的mNativeContext
static int cn_hongda_opengl_opengles_MyGLView_init(JNIEnv *env, jobject obj)
{
    jclass clazz = env->FindClass(className.c_str());
    if (clazz == nullptr)
    {
        LOGE("can't find class %s", className.c_str());
        return -1;
    }
    gFields.context = env->GetFieldID(clazz, "mNativeContext", "J");
    if (nullptr == gFields.context)
    {
        LOGE("can't find field mNativeContext.");
        return 0;
    }
}

//每次通过gFields.context获取c++对象指针
static MyGLView *getMyGLView(JNIEnv *env, jobject obj)
{
    return (MyGLView *)env->GetLongField(obj, gFields.context);
}

//创建底层C++ MyGLView对象
static int cn_hongda_opengl_opengles_MyGLView_create(JNIEnv *env, jobject obj ,jint width, jint height)
{
    MyGLView * myGLView = new MyGLView();
    MyGLView *oldMyGLView = (MyGLView*) env->GetLongField(obj, gFields.context);
    //如果有旧的对象指针存在,释放该对象
    if (oldGLMyGLView != nullptr)
    {
        delete oldGLMyGLView;
    }
    myGLView->initGlContext(width, height);
    //将新创建的C++对象指针,保存到gFields.context,因为java对象的mNativeContext已经与之形成映射关系,所以,这时候mNativeContext也已经被赋值
    env->SetLongField(obj, gFields.context, (jlong) myGLView);
    return 0;
}

总结:
该方法宗旨是将C++对象指针反向写到java对象中,然后在jni接口用一个变量与之对应,使用到c++对象时,直接通过jni接口中的那个变量转成C++对象指针。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JNIJava Native Interface)是Java提供的一种机制,用于实现Java与其他语言(如C++)之间的交互。在JNI中,可以使用C++代码来操作Java对象。 智能指针是一种C++中的资源管理工具,用于自动管理动态分配的内存。在JNI中,可以使用智能指针来管理Java对象的内存。 在使用JNI写入Java DTO时,可以使用智能指针NewByteArray来创建一个字节数组,并将数据写入该字节数组,然后将字节数组递给Java DTO对象。 以下是使用JNI和智能指针NewByteArray写入Java DTO的示例代码: ```cpp #include <jni.h> #include <memory> JNIEXPORT void JNICALL Java_com_example_MyClass_writeToDTO(JNIEnv* env, jobject obj, jobject dtoObj, jbyteArray data) { // 获取DTO类及其字段ID jclass dtoClass = env->GetObjectClass(dtoObj); jfieldID fieldId = env->GetFieldID(dtoClass, "data", "[B"); // 创建智能指针NewByteArray,并获取字节数组指针 jbyteArray newArray = env->NewByteArray(env->GetArrayLength(data)); std::unique_ptr<jbyte, void(*)(JNIEnv*, jbyteArray)> arrayPtr(env, newArray); jbyte* arrayData = env->GetByteArrayElements(newArray, nullptr); // 将数据写入字节数组 jsize dataSize = env->GetArrayLength(data); jbyte* dataPtr = env->GetByteArrayElements(data, nullptr); memcpy(arrayData, dataPtr, dataSize); env->ReleaseByteArrayElements(data, dataPtr, JNI_ABORT); // 将字节数组设置到DTO对象的字段中 env->SetObjectField(dtoObj, fieldId, newArray); } ``` 在上述代码中,我们首先获取DTO类及其字段ID,然后创建智能指针NewByteArray,并获取字节数组指针。接着,我们将数据从原始的jbyteArray复制到字节数组中,并将字节数组设置到DTO对象的字段中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值