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++对象指针。