JNIc++对象与java对象互关联
android中如果需要调⽤c++代码需要写jni将java操作转接到c++代码中.但是⼤部分的⽂章都只是通过讲解通过 extern "C" 代码来访问具体功能.
在这⾥我要讲⼀种⽅便的⽅法将java对象和c++对象互相绑定起来.
第⼀步:
JNIObject.java:
public class JNIObject {
protected long mObj;
}
MediaController.java
public class MediaController extends JNIObject {
public MediaController()
{
tapered
construct();
}membrane
@Override
protected void finalize() throws Throwable {
destruct();
super.finalize();
}
@Keep
private void logMessage(String msg){
Log.d("AAA", "msg:"+msg);
}
static {
System.loadLibrary("media_controller-lib");
}
private native void construct();
private native void destruct();
public native int ntopen(String file);
public native void ntclo();
public native int ntplay();
public native void ntpau();
public native void ntek(int c);
public native String nttest(int msg);
}
jni代码:
圣诞的英文static JavaVM* g_VM = NULL;
class JNIMediaControl
:public MediaControl
{
public:
JNIMediaControl()
:javaVM(NULL),env_(NULL),thiz(NULL)
{
}
void attachParent(JavaVM * vm,JNIEnv *env,jobject object)
{
javaVM =vm;
thiz = env->NewGlobalRef(object);
}
void detachParent(JNIEnv *env)
{
env->DeleteGlobalRef(thiz);
在线英语阅读助手thiz = NULL;
}devil是什么意思
private:
void AttachThread()
{
去职if(javaVM == NULL) return;
if(thiz == NULL) return ;
int ret = javaVM->AttachCurrentThread(&env_,NULL);
if(ret != 0)
少儿频道动漫世界
{
}
}
void DetachThread()
{
if(javaVM == NULL) return;
javaVM->DetachCurrentThread();
env_ = NULL;
}
virtual void Run()
{
AttachThread();
MediaControl::Run();
DetachThread();
}
void SendPacket(int64_t timestamp,AVFrame *frame)
{
JNIEnv *env = env_;
if(env == NULL) return;
char buffer[64];
sprintf(buffer,"%lld",timestamp);
jstring msg_ = env->NewStringUTF(buffer);
jclass clazz = env->GetObjectClass(thiz);
jmethodID jid = env->GetMethodID(clazz,"logMessage","(Ljava/lang/String;)V"); env->CallVoidMethod(thiz,jid,msg_);
env->DeleteLocalRef(msg_);
}
private:
JavaVM* javaVM;
JNIEnv *env_;延世
jobject thiz;
};
#define CONSTRUCT(T) { T *t = new T(); \
jclass clazz = (jclass)(*env).GetObjectClass(thiz); \
jfieldID fid = (jfieldID)(*env).GetFieldID(clazz, "mObj", "J"); \
jlong jstr = (jlong) (*env).GetLongField(thiz, fid); \
(*env).SetLongField(thiz, fid, (jlong)t);}
#define OBJECT(T,name) jclass clazz = (jclass)env->GetObjectClass(thiz); \
jfieldID fid = env->GetFieldID(clazz, "mObj","J"); \
T *name = (T *)env->GetLongField(thiz, fid);
#define DESTRUCT(T) {jclass clazz = (jclass)env->GetObjectClass(thiz); \
jfieldID fid = env->GetFieldID(clazz, "mObj","J"); \
T *object = (T *)env->GetLongField(thiz, fid); \
if(object != NULL) delete object; \
(*env).SetLongField(thiz, fid, (jlong)0);}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_jfyang_mediacontrollerdemo_MediaController_construct(JNIEnv* env, jobject thiz){ CONSTRUCT(JNIMediaControl);
OBJECT(JNIMediaControl,control);
if(control == NULL) return ;
control->attachParent(g_VM,env,thiz);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_jfyang_mediacontrollerdemo_MediaController_destruct(JNIEnv *env,
jobject thiz) {
{
OBJECT(JNIMediaControl, control);
if (control == NULL) return;
control->detachParent(env);
}
DESTRUCT(JNIMediaControl);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_jfyang_mediacontrollerdemo_MediaController_ntclo(JNIEnv *env,
jobject thiz) {
OBJECT(JNIMediaControl,control);
if(control == NULL) return ;
control->Clo();
}
vanclJNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* rerved)
{
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return -1;
}
asrt(env != NULL);
g_VM = vm;
return JNI_VERSION_1_4;
}
在android中需要被底层使⽤的对象均继承⾃JNIObject.
JNI代码中 通过
CONSTRUCT构造⼀个⾃定义对象与JNIObject关联起来.
OBJECT获取与JNIObject关联起来的对象
DESTRUCT释放与JNIObject关联起来的对象
具体的功能还是通过jni的c⽅法调⽤并转⾄c++对象中.
在jni底层线程中有时需要回调数据⾄android上层中,这种情况我们可以通过回调上层⽅法完成.
1.先将上层⽗对象建⽴全局引⽤
thiz = env->NewGlobalRef(object);
英语翻译软件注意:所有的在底层线程中操作的上层对象均需要建⽴GlobalRef才能使⽤,否则会崩溃.
2.通过JNI_Onload获取本模块加载时传⼊的虚拟机并全局保存
3.通过虚拟机 在线程中创建⼀个线程相关JNIEnv.
4.通过线程相关JNIEnv 调⽤ GlobalRef对象的⽅法.