JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv * env, jobject p_obj, jint ID, jstring method, jobjectArray params) { Object* obj = ObjectDB::get_instance(ID); ERR_FAIL_COND(!obj); int res = env->PushLocalFrame(16); ERR_FAIL_COND(res!=0); String str_method = env->GetStringUTFChars( method, NULL ); int count = env->GetArrayLength(params); Variant* vlist = (Variant*)alloca(sizeof(Variant) * count); Variant** vptr = (Variant**)alloca(sizeof(Variant*) * count); for (int i=0; i<count; i++) { jobject obj = env->GetObjectArrayElement(params, i); Variant v; if (obj) v=_jobject_to_variant(env, obj); memnew_placement(&vlist[i], Variant); vlist[i] = v; vptr[i] = &vlist[i]; env->DeleteLocalRef(obj); }; Variant::CallError err; obj->call(str_method, (const Variant**)vptr, count, err); // something env->PopLocalFrame(NULL); };
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv * env, jobject p_obj, jint ID, jstring method, jobjectArray params) { Object* obj = ObjectDB::get_instance(ID); ERR_FAIL_COND(!obj); int res = env->PushLocalFrame(16); ERR_FAIL_COND(res!=0); String str_method = env->GetStringUTFChars( method, NULL ); int count = env->GetArrayLength(params); Variant args[VARIANT_ARG_MAX]; //print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count)); for (int i=0; i<MIN(count,VARIANT_ARG_MAX); i++) { jobject obj = env->GetObjectArrayElement(params, i); if (obj) args[i] = _jobject_to_variant(env, obj); env->DeleteLocalRef(obj); // print_line("\targ"+itos(i)+": "+Variant::get_type_name(args[i].get_type())); }; obj->call_deferred(str_method, args[0],args[1],args[2],args[3],args[4]); // something env->PopLocalFrame(NULL); };
JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_calldeferred(JNIEnv * env, jobject p_obj, jint ID, jstring method, jobjectArray params) { String str_method = env->GetStringUTFChars( method, NULL ); Object* obj = ObjectDB::get_instance(ID); ERR_FAIL_COND(!obj); int count = env->GetArrayLength(params); Variant args[VARIANT_ARG_MAX]; for (int i=0; i<MIN(count,VARIANT_ARG_MAX); i++) { jobject obj = env->GetObjectArrayElement(params, i); args[i] = _jobject_to_variant(env, obj); }; obj->call_deferred(str_method, args[0],args[1],args[2],args[3],args[4]); // something };
virtual Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error) { //print_line("attempt to call "+String(p_method)); ERR_FAIL_COND_V(!instance,Variant()); r_error.error=Variant::CallError::CALL_OK; Map<StringName,MethodData >::Element *E=method_map.find(p_method); if (!E) { print_line("no exists"); r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; return Variant(); } int ac = E->get().argtypes.size(); if (ac<p_argcount) { print_line("fewargs"); r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument=ac; return Variant(); } if (ac>p_argcount) { print_line("manyargs"); r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.argument=ac; return Variant(); } for(int i=0;i<p_argcount;i++) { if (!Variant::can_convert(p_args[i]->get_type(),E->get().argtypes[i])) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=i; r_error.expected=E->get().argtypes[i]; } } jvalue *v=NULL; if (p_argcount) { v=(jvalue*)alloca( sizeof(jvalue)*p_argcount ); } JNIEnv *env = ThreadAndroid::get_env(); int res = env->PushLocalFrame(16); ERR_FAIL_COND_V(res!=0,Variant()); //print_line("argcount "+String::num(p_argcount)); List<jobject> to_erase; for(int i=0;i<p_argcount;i++) { jvalret vr = _variant_to_jvalue(env, E->get().argtypes[i], p_args[i]); v[i] = vr.val; if (vr.obj) to_erase.push_back(vr.obj); } //print_line("calling method!!"); Variant ret; switch(E->get().ret_type) { case Variant::NIL: { //print_line("call void"); env->CallVoidMethodA(instance,E->get().method,v); } break; case Variant::BOOL: { ret = env->CallBooleanMethodA(instance,E->get().method,v); //print_line("call bool"); } break; case Variant::INT: { ret = env->CallIntMethodA(instance,E->get().method,v); //print_line("call int"); } break; case Variant::REAL: { ret = env->CallFloatMethodA(instance,E->get().method,v); } break; case Variant::STRING: { jobject o = env->CallObjectMethodA(instance,E->get().method,v); String str = env->GetStringUTFChars((jstring)o, NULL ); ret=str; env->DeleteLocalRef(o); } break; case Variant::STRING_ARRAY: { jobjectArray arr = (jobjectArray)env->CallObjectMethodA(instance,E->get().method,v); ret = _jobject_to_variant(env, arr); env->DeleteLocalRef(arr); } break; case Variant::INT_ARRAY: { jintArray arr = (jintArray)env->CallObjectMethodA(instance,E->get().method,v); int fCount = env->GetArrayLength(arr); DVector<int> sarr; sarr.resize(fCount); DVector<int>::Write w = sarr.write(); env->GetIntArrayRegion(arr,0,fCount,w.ptr()); w = DVector<int>::Write(); ret=sarr; env->DeleteLocalRef(arr); } break; case Variant::REAL_ARRAY: { jfloatArray arr = (jfloatArray)env->CallObjectMethodA(instance,E->get().method,v); int fCount = env->GetArrayLength(arr); DVector<float> sarr; sarr.resize(fCount); DVector<float>::Write w = sarr.write(); env->GetFloatArrayRegion(arr,0,fCount,w.ptr()); w = DVector<float>::Write(); ret=sarr; env->DeleteLocalRef(arr); } break; case Variant::DICTIONARY: { //print_line("call dictionary"); jobject obj = env->CallObjectMethodA(instance, E->get().method, v); ret = _jobject_to_variant(env, obj); env->DeleteLocalRef(obj); } break; default: { print_line("failure.."); env->PopLocalFrame(NULL); ERR_FAIL_V(Variant()); } break; } while (to_erase.size()) { env->DeleteLocalRef(to_erase.front()->get()); to_erase.pop_front(); } env->PopLocalFrame(NULL); //print_line("success"); return ret; }
Variant _jobject_to_variant(JNIEnv * env, jobject obj) { jclass c = env->GetObjectClass(obj); bool array; String name = _get_class_name(env, c, &array); //print_line("name is " + name + ", array "+Variant(array)); print_line("ARGNAME: "+name); if (name == "java.lang.String") { return String::utf8(env->GetStringUTFChars( (jstring)obj, NULL )); }; if (name == "[Ljava.lang.String;") { jobjectArray arr = (jobjectArray)obj; int stringCount = env->GetArrayLength(arr); //print_line("String array! " + String::num(stringCount)); DVector<String> sarr; for (int i=0; i<stringCount; i++) { jstring string = (jstring) env->GetObjectArrayElement(arr, i); const char *rawString = env->GetStringUTFChars(string, 0); sarr.push_back(String(rawString)); env->DeleteLocalRef(string); } return sarr; }; if (name == "java.lang.Boolean") { jmethodID boolValue = env->GetMethodID(c, "booleanValue", "()Z"); bool ret = env->CallBooleanMethod(obj, boolValue); return ret; }; if (name == "java.lang.Integer") { jclass nclass = env->FindClass("java/lang/Number"); jmethodID intValue = env->GetMethodID(nclass, "intValue", "()I"); int ret = env->CallIntMethod(obj, intValue); return ret; }; if (name == "[I") { jintArray arr = (jintArray)obj; int fCount = env->GetArrayLength(arr); DVector<int> sarr; sarr.resize(fCount); DVector<int>::Write w = sarr.write(); env->GetIntArrayRegion(arr,0,fCount,w.ptr()); w = DVector<int>::Write(); return sarr; }; if (name == "[B") { jbyteArray arr = (jbyteArray)obj; int fCount = env->GetArrayLength(arr); DVector<uint8_t> sarr; sarr.resize(fCount); DVector<uint8_t>::Write w = sarr.write(); env->GetByteArrayRegion(arr,0,fCount,reinterpret_cast<signed char*>(w.ptr())); w = DVector<uint8_t>::Write(); return sarr; }; if (name == "java.lang.Float" || name == "java.lang.Double") { jclass nclass = env->FindClass("java/lang/Number"); jmethodID doubleValue = env->GetMethodID(nclass, "doubleValue", "()D"); double ret = env->CallDoubleMethod(obj, doubleValue); return ret; }; if (name == "[D") { jdoubleArray arr = (jdoubleArray)obj; int fCount = env->GetArrayLength(arr); RealArray sarr; sarr.resize(fCount); RealArray::Write w = sarr.write(); for (int i=0; i<fCount; i++) { double n; env->GetDoubleArrayRegion(arr, i, 1, &n); w.ptr()[i] = n; }; return sarr; }; if (name == "[F") { jfloatArray arr = (jfloatArray)obj; int fCount = env->GetArrayLength(arr); RealArray sarr; sarr.resize(fCount); RealArray::Write w = sarr.write(); for (int i=0; i<fCount; i++) { float n; env->GetFloatArrayRegion(arr, i, 1, &n); w.ptr()[i] = n; }; return sarr; }; if (name == "[Ljava.lang.Object;") { jobjectArray arr = (jobjectArray)obj; int objCount = env->GetArrayLength(arr); Array varr(true); for (int i=0; i<objCount; i++) { jobject jobj = env->GetObjectArrayElement(arr, i); Variant v = _jobject_to_variant(env, jobj); varr.push_back(v); env->DeleteLocalRef(jobj); } return varr; }; if (name == "java.util.HashMap" || name == "org.godotengine.godot.Dictionary") { Dictionary ret(true); jclass oclass = c; jmethodID get_keys = env->GetMethodID(oclass, "get_keys", "()[Ljava/lang/String;"); jobjectArray arr = (jobjectArray)env->CallObjectMethod(obj, get_keys); StringArray keys = _jobject_to_variant(env, arr); env->DeleteLocalRef(arr); jmethodID get_values = env->GetMethodID(oclass, "get_values", "()[Ljava/lang/Object;"); arr = (jobjectArray)env->CallObjectMethod(obj, get_values); Array vals = _jobject_to_variant(env, arr); env->DeleteLocalRef(arr); //print_line("adding " + String::num(keys.size()) + " to Dictionary!"); for (int i=0; i<keys.size(); i++) { ret[keys[i]] = vals[i]; }; return ret; }; env->DeleteLocalRef(c); return Variant(); };