// // Created by Fear1ess on 2021/4/1. // #include "wd_jni.h" #include "wdun.h" #define WD_JNI "wd_jni" void wdCheckException(JNIEnv* env) { if((*env)->ExceptionOccurred(env) != NULL){ (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } } char wdGetMethodRetType(const char* sig) { char* p = (char*)sig; // skip '()' to find out the return type while (*p != ')'){ p++; } // skip ')' p++; return *p; } jvalue wdGetStaticField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig) { jclass cls = (*env)->FindClass(env, clsName); jfieldID fieldId = (*env)->GetStaticFieldID(env, cls, fieldName, fieldSig); jvalue value = {0}; switch(wdGetFieldType(fieldSig)) { case '[': case 'L': value.l = (*env)->GetStaticObjectField(env, cls, fieldId); break; case 'Z': value.z = (*env)->GetStaticBooleanField(env, cls, fieldId); break; case 'B': value.b = (*env)->GetStaticByteField(env, cls, fieldId); break; case 'C': value.c = (*env)->GetStaticCharField(env, cls, fieldId); break; case 'S': value.s = (*env)->GetStaticShortField(env, cls, fieldId); break; case 'I': value.i = (*env)->GetStaticIntField(env, cls, fieldId); break; case 'J': value.j = (*env)->GetStaticLongField(env, cls, fieldId); break; case 'F': value.f = (*env)->GetStaticFloatField(env, cls, fieldId); break; case 'D': value.d = (*env)->GetStaticDoubleField(env, cls, fieldId); break; default: break; } wdCheckException(env); (*env)->DeleteLocalRef(env, cls); return value; } jvalue wdGetField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig) { jclass cls = (*env)->GetObjectClass(env, obj); jfieldID fieldId = (*env)->GetFieldID(env, cls, fieldName, fieldSig); jvalue value = {0}; switch(wdGetFieldType(fieldSig)) { case '[': case 'L': value.l = (*env)->GetObjectField(env, obj, fieldId); break; case 'Z': value.z = (*env)->GetBooleanField(env, obj, fieldId); break; case 'B': value.b = (*env)->GetByteField(env, obj, fieldId); break; case 'C': value.c = (*env)->GetCharField(env, obj, fieldId); break; case 'S': value.s = (*env)->GetShortField(env, obj, fieldId); break; case 'I': value.i = (*env)->GetIntField(env, obj, fieldId); break; case 'J': value.j = (*env)->GetLongField(env, obj, fieldId); break; case 'F': value.f = (*env)->GetFloatField(env, obj, fieldId); break; case 'D': value.d = (*env)->GetDoubleField(env, obj, fieldId); break; default: break; } wdCheckException(env); (*env)->DeleteLocalRef(env, cls); return value; } void wdSetStaticField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig, jvalue value) { jclass cls = (*env)->FindClass(env, clsName); jfieldID fieldId = (*env)->GetStaticFieldID(env, cls, fieldName, fieldSig); switch(wdGetFieldType(fieldSig)) { case '[': case 'L': (*env)->SetStaticObjectField(env, cls, fieldId, value.l); break; case 'Z': (*env)->SetStaticBooleanField(env, cls, fieldId, value.z); break; case 'B': (*env)->SetStaticByteField(env, cls, fieldId, value.b); break; case 'C': (*env)->SetStaticCharField(env, cls, fieldId, value.c); break; case 'S': (*env)->SetStaticShortField(env, cls, fieldId, value.s); break; case 'I': (*env)->SetStaticIntField(env, cls, fieldId, value.i); break; case 'J': (*env)->SetStaticLongField(env, cls, fieldId, value.j); break; case 'F': (*env)->SetStaticFloatField(env, cls, fieldId, value.f); break; case 'D': (*env)->SetStaticDoubleField(env, cls, fieldId, value.d); break; default: break; } wdCheckException(env); (*env)->DeleteLocalRef(env, cls); } void wdSetField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig, jvalue value) { jclass cls = (*env)->GetObjectClass(env, cls); jfieldID fieldId = (*env)->GetFieldID(env, cls, fieldName, fieldSig); switch(wdGetFieldType(fieldSig)) { case '[': case 'L': (*env)->SetObjectField(env, obj, fieldId, value.l); break; case 'Z': (*env)->SetBooleanField(env, obj, fieldId, value.z); break; case 'B': (*env)->SetByteField(env, obj, fieldId, value.b); break; case 'C': (*env)->SetCharField(env, obj, fieldId, value.c); break; case 'S': (*env)->SetShortField(env, obj, fieldId, value.s); break; case 'I': (*env)->SetIntField(env, obj, fieldId, value.i); break; case 'J': (*env)->SetLongField(env, obj, fieldId, value.j); break; case 'F': (*env)->SetFloatField(env, obj, fieldId, value.f); break; case 'D': (*env)->SetDoubleField(env, obj, fieldId, value.d); break; default: break; } wdCheckException(env); (*env)->DeleteLocalRef(env, cls); } jobject wdNewObject(JNIEnv* env, const char* clsName, const char* methodSig, ...) { jclass cls = (*env)->FindClass(env, clsName); jmethodID methodId = (*env)->GetMethodID(env, cls, "<init>", methodSig); va_list args; va_start(args, methodSig); jobject res = NULL; res = (*env)->NewObjectV(env, cls, methodId, args); wdCheckException(env); va_end(args); (*env)->DeleteLocalRef(env, cls); return res; } jvalue wdCallStaticMethod(JNIEnv* env, const char* clsName, const char* methodName, const char* methodSig, va_list args) { jclass cls = (*env)->FindClass(env, clsName); if(cls == NULL) { logd(WD_JNI, "not find class %s", clsName); goto return_label; } jmethodID methodId = (*env)->GetStaticMethodID(env, cls, methodName, methodSig); if(methodId == NULL) { logd(WD_JNI, "not find method %s->%s%s", clsName, methodName, methodSig); goto return_label; } jvalue value = {0}; switch(wdGetMethodRetType(methodSig)) { case 'V': (*env)->CallStaticVoidMethodV(env, cls, methodId, args); break; case '[': case 'L': value.l = (*env)->CallStaticObjectMethodV (env, cls, methodId, args); break; case 'Z': value.z = (*env)->CallStaticBooleanMethodV(env, cls, methodId, args); break; case 'B': value.b = (*env)->CallStaticByteMethodV(env, cls, methodId, args); break; case 'C': value.c = (*env)->CallStaticCharMethodV(env, cls, methodId, args); break; case 'S': value.s = (*env)->CallStaticShortMethodV(env, cls, methodId, args); break; case 'I': value.i = (*env)->CallStaticIntMethodV(env, cls, methodId, args); break; case 'J': value.j = (*env)->CallStaticLongMethodV(env, cls, methodId, args); break; case 'F': value.f = (*env)->CallStaticFloatMethodV(env, cls, methodId, args); break; case 'D': value.d = (*env)->CallStaticDoubleMethodV(env, cls, methodId, args); break; default: break; } wdCheckException(env); return_label: (*env)->DeleteLocalRef(env, cls); return value; } jvalue wdCallMethod(JNIEnv* env, jobject obj, const char* methodName, const char* methodSig, va_list args) { jclass cls = (*env)->GetObjectClass(env, obj); jmethodID methodId = (*env)->GetMethodID(env, cls, methodName, methodSig); jvalue value = {0}; switch(wdGetMethodRetType(methodSig)) { case 'V': (*env)->CallVoidMethodV(env, obj, methodId, args); break; case '[': case 'L': value.l = (*env)->CallObjectMethodV (env, obj, methodId, args); break; case 'Z': value.z = (*env)->CallBooleanMethodV(env, obj, methodId, args); break; case 'B': value.b = (*env)->CallByteMethodV(env, obj, methodId, args); break; case 'C': value.c = (*env)->CallCharMethodV(env, obj, methodId, args); break; case 'S': value.s = (*env)->CallShortMethodV(env, obj, methodId, args); break; case 'I': value.i = (*env)->CallIntMethodV(env, obj, methodId, args); break; case 'J': value.j = (*env)->CallLongMethodV(env, obj, methodId, args); break; case 'F': value.f = (*env)->CallFloatMethodV(env, obj, methodId, args); break; case 'D': value.d = (*env)->CallDoubleMethodV(env, obj, methodId, args); break; default: break; } wdCheckException(env); (*env)->DeleteLocalRef(env, cls); return value; } jboolean wdCallStaticBooleanMethod(JNIEnv* env, const char* clsName, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jboolean res = wdCallStaticMethod(env, clsName, methodName, methodSig, args).z; va_end(args); return res; } jbyte wdCallStaticByteMethod(JNIEnv* env, const char* clsName, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jboolean res = wdCallStaticMethod(env, clsName, methodName, methodSig, args).b; va_end(args); return res; } jchar wdCallStaticCharMethod(JNIEnv* env, const char* clsName, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jchar res = wdCallStaticMethod(env, clsName, methodName, methodSig, args).c; va_end(args); return res; } jshort wdCallStaticShortMethod(JNIEnv* env, const char* clsName, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jshort res = wdCallStaticMethod(env, clsName, methodName, methodSig, args).s; va_end(args); return res; } jint wdCallStaticIntMethod(JNIEnv* env, const char* clsName, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jint res = wdCallStaticMethod(env, clsName, methodName, methodSig, args).i; va_end(args); return res; } jlong wdCallStaticLongMethod(JNIEnv* env, const char* clsName, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jlong res = wdCallStaticMethod(env, clsName, methodName, methodSig, args).j; va_end(args); return res; } jfloat wdCallStaticFloatMethod(JNIEnv* env, const char* clsName, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jfloat res = wdCallStaticMethod(env, clsName, methodName, methodSig, args).f; va_end(args); return res; } jdouble wdCallStaticDoubleMethod(JNIEnv* env, const char* clsName, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jdouble res = wdCallStaticMethod(env, clsName, methodName, methodSig, args).d; va_end(args); return res; } jobject wdCallStaticObjectMethod(JNIEnv* env, const char* clsName, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jobject res = wdCallStaticMethod(env, clsName, methodName, methodSig, args).l; va_end(args); return res; } void wdCallStaticVoidMethod(JNIEnv* env, const char* clsName, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); wdCallStaticMethod(env, clsName, methodName, methodSig, args); va_end(args); } jboolean wdCallBooleanMethod(JNIEnv* env, jobject obj, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jboolean res = wdCallMethod(env, obj, methodName, methodSig, args).z; va_end(args); return res; } jbyte wdCallByteMethod(JNIEnv* env, jobject obj, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jboolean res = wdCallMethod(env, obj, methodName, methodSig, args).b; va_end(args); return res; } jchar wdCallCharMethod(JNIEnv* env, jobject obj, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jchar res = wdCallMethod(env, obj, methodName, methodSig, args).c; va_end(args); return res; } jshort wdCallShortMethod(JNIEnv* env, jobject obj, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jshort res = wdCallMethod(env, obj, methodName, methodSig, args).s; va_end(args); return res; } jint wdCallIntMethod(JNIEnv* env, jobject obj, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jint res = wdCallMethod(env, obj, methodName, methodSig, args).i; va_end(args); return res; } jlong wdCallLongMethod(JNIEnv* env, jobject obj, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jlong res = wdCallMethod(env, obj, methodName, methodSig, args).j; va_end(args); return res; } jfloat wdCallFloatMethod(JNIEnv* env, jobject obj, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jfloat res = wdCallMethod(env, obj, methodName, methodSig, args).f; va_end(args); return res; } jdouble wdCallDoubleMethod(JNIEnv* env, jobject obj, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jdouble res = wdCallMethod(env, obj, methodName, methodSig, args).d; va_end(args); return res; } jobject wdCallObjectMethod(JNIEnv* env, jobject obj, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); jobject res = wdCallMethod(env, obj, methodName, methodSig, args).l; va_end(args); return res; } void wdCallVoidMethod(JNIEnv* env, jobject obj, const char* methodName, const char* methodSig, ...) { va_list args; va_start(args, methodSig); wdCallMethod(env, obj, methodName, methodSig, args); va_end(args); } jboolean wdGetStaticBooleanField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig) { return wdGetStaticField(env, clsName, fieldName, fieldSig).z; } jbyte wdGetStaticByteField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig) { return wdGetStaticField(env, clsName, fieldName, fieldSig).b; } jchar wdGetStaticCharField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig) { return wdGetStaticField(env, clsName, fieldName, fieldSig).c; } jshort wdGetStaticShortField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig) { return wdGetStaticField(env, clsName, fieldName, fieldSig).s; } jint wdGetStaticIntField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig) { return wdGetStaticField(env, clsName, fieldName, fieldSig).i; } jlong wdGetStaticLongField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig) { return wdGetStaticField(env, clsName, fieldName, fieldSig).j; } jfloat wdGetStaticFloatField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig) { return wdGetStaticField(env, clsName, fieldName, fieldSig).f; } jdouble wdGetStaticDoubleField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig) { return wdGetStaticField(env, clsName, fieldName, fieldSig).d; } jobject wdGetStaticObjectField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig) { return wdGetStaticField(env, clsName, fieldName, fieldSig).l; } jboolean wdGetBooleanField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig) { return wdGetField(env, obj, fieldName, fieldSig).z; } jbyte wdGetByteField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig) { return wdGetField(env, obj, fieldName, fieldSig).b; } jchar wdGetCharField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig) { return wdGetField(env, obj, fieldName, fieldSig).c; } jshort wdGetShortField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig) { return wdGetField(env, obj, fieldName, fieldSig).s; } jint wdGetIntField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig) { return wdGetField(env, obj, fieldName, fieldSig).i; } jlong wdGetLongField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig) { return wdGetField(env, obj, fieldName, fieldSig).j; } jfloat wdGetFloatField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig) { return wdGetField(env, obj, fieldName, fieldSig).f; } jdouble wdGetDoubleField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig) { return wdGetField(env, obj, fieldName, fieldSig).d; } jobject wdGetObjectField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig) { return wdGetField(env, obj, fieldName, fieldSig).l; } void wdSetStaticBooleanField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig, jboolean value) { jvalue j = {.z = value}; wdSetStaticField(env, clsName, fieldName, fieldSig, j); } void wdSetStaticByteField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig, jbyte value) { jvalue j = {.b = value}; wdSetStaticField(env, clsName, fieldName, fieldSig, j); } void wdSetStaticCharField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig, jchar value) { jvalue j = {.c = value}; wdSetStaticField(env, clsName, fieldName, fieldSig, j); } void wdSetStaticShortField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig, jshort value) { jvalue j = {.s = value}; wdSetStaticField(env, clsName, fieldName, fieldSig, j); } void wdSetStaticIntField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig, jint value) { jvalue j = {.i = value}; wdSetStaticField(env, clsName, fieldName, fieldSig, j); } void wdSetStaticLongField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig, jlong value) { jvalue j = {.j = value}; wdSetStaticField(env, clsName, fieldName, fieldSig, j); } void wdSetStaticFloatField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig, jfloat value) { jvalue j = {.f = value}; wdSetStaticField(env, clsName, fieldName, fieldSig, j); } void wdSetStaticDoubleField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig, jdouble value) { jvalue j = {.d = value}; wdSetStaticField(env, clsName, fieldName, fieldSig, j); } void wdSetStaticObjectField(JNIEnv* env, const char* clsName, const char* fieldName, const char* fieldSig, jobject value) { jvalue j = {.l = value}; wdSetStaticField(env, clsName, fieldName, fieldSig, j); } void wdSetBooleanField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig, jboolean value) { jvalue j = {.z = value}; wdSetField(env, obj, fieldName, fieldSig, j); } void wdSetByteField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig, jbyte value) { jvalue j = {.b = value}; wdSetField(env, obj, fieldName, fieldSig, j); } void wdSetCharField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig, jchar value) { jvalue j = {.c = value}; wdSetField(env, obj, fieldName, fieldSig, j); } void wdSetShortField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig, jshort value) { jvalue j = {.s = value}; wdSetField(env, obj, fieldName, fieldSig, j); } void wdSetIntField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig, jint value) { jvalue j = {.i = value}; wdSetField(env, obj, fieldName, fieldSig, j); } void wdSetLongField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig, jlong value) { jvalue j = {.j = value}; wdSetField(env, obj, fieldName, fieldSig, j); } void wdSetFloatField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig, jfloat value) { jvalue j = {.f = value}; wdSetField(env, obj, fieldName, fieldSig, j); } void wdSetDoubleField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig, jdouble value) { jvalue j = {.d = value}; wdSetField(env, obj, fieldName, fieldSig, j); } void wdSetObjectField(JNIEnv* env, jobject obj, const char* fieldName, const char* fieldSig, jobject value) { jvalue j = {.l = value}; wdSetField(env, obj, fieldName, fieldSig, j); } char wdGetFieldType(const char* sig) { return *sig; }