HostRef* JPMethodOverload::invokeInstance(vector<HostRef*>& args) { TRACE_IN("JPMethodOverload::invokeInstance"); HostRef* res; { JPCleaner cleaner; // Arg 0 is "this" HostRef* self = args[0]; JPObject* selfObj = JPEnv::getHost()->asObject(self); size_t len = args.size(); JPMallocCleaner<jvalue> v(len-1); for (unsigned int i = 1; i < len; i++) { HostRef* obj = args[i]; JPType* type = JPTypeManager::getType(m_Arguments[i]); v[i-1] = type->convertToJava(obj); // below seems not to be necessary, since jvalues are clean by jpmalloccleaner // if (type->isObjectType()) // { // //TODO : investigate: this is not valid for either local or global ref // // add hostref to garbage collection // cleaner.add(v[i-1].l); // } } JPType* retType = JPTypeManager::getType(m_ReturnType); jobject c = selfObj->getObject(); cleaner.addLocal(c); jclass clazz = m_Class->getClass(); cleaner.addGlobal(clazz); res = retType->invoke(c, clazz, m_MethodID, v.borrow()); TRACE1("Call finished"); } TRACE1("Call successfull"); return res; TRACE_OUT; }
jvalue JPStringType::convertToJava(HostRef* obj) { TRACE_IN("JPStringType::convertToJava"); JPCleaner cleaner; jvalue v; if (JPEnv::getHost()->isNone(obj)) { v.l = NULL; return v; } if (JPEnv::getHost()->isWrapper(obj)) { return JPEnv::getHost()->getWrapperValue(obj); } if (JPEnv::getHost()->isObject(obj)) { JPObject* o = JPEnv::getHost()->asObject(obj); JPClass* oc = o->getClass(); if (oc->getName().getSimpleName() == "java.lang.String") { v.l = o->getObject(); return v; } } JCharString wstr = JPEnv::getHost()->stringAsJCharString(obj); jchar* jstr = new jchar[wstr.length()+1]; jstr[wstr.length()] = 0; for (size_t i = 0; i < wstr.length(); i++) { jstr[i] = (jchar)wstr[i]; } jstring res = JPEnv::getJava()->NewString(jstr, (jint)wstr.length()); delete[] jstr; v.l = res; return v; TRACE_OUT; }
jobject JPPrimitiveType::convertToJavaObject(HostRef* obj) { JPCleaner cleaner; JPTypeName tname = getObjectType(); JPClass* c = JPTypeManager::findClass(tname); jclass jc = c->getClass(); cleaner.addLocal(jc); vector<HostRef*> args(1); args[0] = obj; JPObject* o = c->newInstance(args); jobject res = o->getObject(); delete o; return res; }
EMatchType JPStringType::canConvertToJava(HostRef* obj) { TRACE_IN("JPStringType::canConvertToJava"); JPCleaner cleaner; if (obj == NULL || JPEnv::getHost()->isNone(obj)) { return _implicit; } if (JPEnv::getHost()->isString(obj)) { return _exact; } if (JPEnv::getHost()->isWrapper(obj)) { JPTypeName name = JPEnv::getHost()->getWrapperTypeName(obj); if (name.getType() == JPTypeName::_string) { return _exact; } } if (JPEnv::getHost()->isObject(obj)) { JPObject* o = JPEnv::getHost()->asObject(obj); JPClass* oc = o->getClass(); if (oc->getName().getSimpleName() == "java.lang.String") { return _exact; } } return _none; TRACE_OUT; }
jvalue JPClass::convertToJava(HostRef* obj) { jvalue res; JPCleaner cleaner; res.l = NULL; // assume it is convertible; if (JPEnv::getHost()->isNone(obj)) { res.l = NULL; } string simpleName = m_Name.getSimpleName(); if (JPEnv::getHost()->isInt(obj) && (simpleName == "java.lang.Byte" || simpleName == "java.lang.Short" || simpleName == "java.lang.Integer")) { return buildObjectWrapper(obj); } if ((JPEnv::getHost()->isInt(obj) || JPEnv::getHost()->isLong(obj)) && simpleName == "java.lang.Long" && JPEnv::getHost()->isLong(obj)) { return buildObjectWrapper(obj); } if (JPEnv::getHost()->isFloat(obj) && (simpleName == "java.lang.Float" || simpleName == "java.lang.Double")) { if (JPEnv::getHost()->isFloat(obj)) { return buildObjectWrapper(obj); } } if (JPEnv::getHost()->isString(obj)) { JPTypeName name = JPTypeName::fromSimple("java.lang.String"); JPType* type = JPTypeManager::getType(name); return type->convertToJava(obj); } if (JPEnv::getHost()->isObject(obj)) { JPObject* ref = JPEnv::getHost()->asObject(obj); res.l = ref->getObject(); } if (JPEnv::getHost()->isProxy(obj)) { JPProxy* proxy = JPEnv::getHost()->asProxy(obj); res.l = proxy->getProxy(); } if (JPEnv::getHost()->isWrapper(obj)) { res = JPEnv::getHost()->getWrapperValue(obj); } if (JPEnv::getHost()->isInt(obj)) { JPTypeName tname = JPTypeName::fromType(JPTypeName::_int); JPType* t = JPTypeManager::getType(tname); res.l = t->convertToJavaObject(obj); } if (JPEnv::getHost()->isLong(obj)) { JPTypeName tname = JPTypeName::fromType(JPTypeName::_long); JPType* t = JPTypeManager::getType(tname); res.l = t->convertToJavaObject(obj); } if (JPEnv::getHost()->isFloat(obj)) { JPTypeName tname = JPTypeName::fromType(JPTypeName::_double); JPType* t = JPTypeManager::getType(tname); res.l = t->convertToJavaObject(obj); } if (JPEnv::getHost()->isBoolean(obj)) { JPTypeName tname = JPTypeName::fromType(JPTypeName::_boolean); JPType* t = JPTypeManager::getType(tname); res.l = t->convertToJavaObject(obj); } if (JPEnv::getHost()->isArray(obj) && simpleName == "java.lang.Object") { JPArray* a = JPEnv::getHost()->asArray(obj); res = a->getValue(); } return res; }
EMatchType JPClass::canConvertToJava(HostRef* obj) { if (JPEnv::getHost()->isNone(obj)) { return _implicit; } JPCleaner cleaner; string simpleName = m_Name.getSimpleName(); if (simpleName == "java.lang.Byte" || simpleName == "java.lang.Short" || simpleName == "java.lang.Integer") { if (JPEnv::getHost()->isInt(obj)) { return _explicit; } } if (simpleName == "java.lang.Long" && JPEnv::getHost()->isLong(obj)) { return _explicit; } if (simpleName == "java.lang.Float" || simpleName == "java.lang.Double") { if (JPEnv::getHost()->isFloat(obj)) { return _explicit; } } if (JPEnv::getHost()->isObject(obj)) { JPObject* o = JPEnv::getHost()->asObject(obj); JPClass* oc = o->getClass(); if (oc == this) { // hey, this is me! :) return _exact; } if (JPEnv::getJava()->IsAssignableFrom(oc->m_Class, m_Class)) { return _implicit; } } if (JPEnv::getHost()->isProxy(obj)) { JPProxy* proxy = JPEnv::getHost()->asProxy(obj); // Check if any of the interfaces matches ... vector<jclass> itf = proxy->getInterfaces(); for (unsigned int i = 0; i < itf.size(); i++) { if (JPEnv::getJava()->IsAssignableFrom(itf[i], m_Class)) { return _implicit; } } } if (JPEnv::getHost()->isWrapper(obj)) { JPTypeName o = JPEnv::getHost()->getWrapperTypeName(obj); if (o.getSimpleName() == m_Name.getSimpleName()) { return _exact; } } if (m_Name.getSimpleName() == "java.lang.Object") { // arrays are objects if (JPEnv::getHost()->isArray(obj)) { return _implicit; } // Strings are objects too if (JPEnv::getHost()->isString(obj)) { return _implicit; } // Class are objects too if (JPEnv::getHost()->isClass(obj) || JPEnv::getHost()->isArrayClass(obj)) { return _implicit; } // Let'a allow primitives (int, long, float and boolean) to convert implicitly too ... if (JPEnv::getHost()->isInt(obj)) { return _implicit; } if (JPEnv::getHost()->isLong(obj)) { return _implicit; } if (JPEnv::getHost()->isFloat(obj)) { return _implicit; } if (JPEnv::getHost()->isBoolean(obj)) { return _implicit; } } return _none; }
JNIEXPORT jobject JNICALL Java_jpype_JPypeInvocationHandler_hostInvoke( JNIEnv *env, jclass clazz, jstring name, jlong hostObj, jobjectArray args, jobjectArray types, jclass returnType) { TRACE_IN("Java_jpype_JPypeInvocationHandler_hostInvoke"); void* callbackState = JPEnv::getHost()->prepareCallbackBegin(); JPCleaner cleaner; try { string cname = JPJni::asciiFromJava(name); HostRef* hostObjRef = (HostRef*)hostObj; HostRef* callable = JPEnv::getHost()->getCallableFrom(hostObjRef, cname); cleaner.add(callable); if (callable == NULL || callable->isNull() || JPEnv::getHost()->isNone(callable)) { JPEnv::getJava()->ThrowNew(JPJni::s_NoSuchMethodErrorClass, cname.c_str()); JPEnv::getHost()->prepareCallbackFinish(callbackState); return NULL; } // convert the arguments into a python list jsize argLen = JPEnv::getJava()->GetArrayLength(types); vector<HostRef*> hostArgs; std::vector<JPTypeName> argTypes; for (jsize j = 0; j < argLen; j++) { jclass c = (jclass)JPEnv::getJava()->GetObjectArrayElement(types, j); cleaner.addLocal(c); JPTypeName tn = JPJni::getName(c); argTypes.push_back(tn); } for (int i = 0; i < argLen; i++) { jobject obj = JPEnv::getJava()->GetObjectArrayElement(args, i); cleaner.addLocal(obj); JPTypeName t = argTypes[i]; jvalue v; v.l = obj; HostRef* o = JPTypeManager::getType(t)->asHostObjectFromObject(v); cleaner.add(o); hostArgs.push_back(o); } HostRef* returnValue = JPEnv::getHost()->callObject(callable, hostArgs); cleaner.add(returnValue); JPTypeName returnT = JPJni::getName(returnType); if (returnValue == NULL || returnValue->isNull() || JPEnv::getHost()->isNone(returnValue)) { if (returnT.getType() != JPTypeName::_void && returnT.getType() < JPTypeName::_object) { JPEnv::getJava()->ThrowNew(JPJni::s_RuntimeExceptionClass, "Return value is None when it cannot be"); JPEnv::getHost()->prepareCallbackFinish(callbackState); return NULL; } } if (returnT.getType() == JPTypeName::_void) { JPEnv::getHost()->prepareCallbackFinish(callbackState); return NULL; } JPType* rt = JPTypeManager::getType(returnT); if (rt->canConvertToJava(returnValue) == _none) { JPEnv::getJava()->ThrowNew(JPJni::s_RuntimeExceptionClass, "Return value is not compatible with required type."); JPEnv::getHost()->prepareCallbackFinish(callbackState); return NULL; } jobject returnObj = rt->convertToJavaObject(returnValue); JPEnv::getHost()->prepareCallbackFinish(callbackState); return returnObj; } catch(HostException* ex) { JPEnv::getHost()->clearError(); if (JPEnv::getHost()->isJavaException(ex)) { JPCleaner cleaner; HostRef* javaExcRef = JPEnv::getHost()->getJavaException(ex); JPObject* javaExc = JPEnv::getHost()->asObject(javaExcRef); cleaner.add(javaExcRef); jobject obj = javaExc->getObject(); cleaner.addLocal(obj); JPEnv::getJava()->Throw((jthrowable)obj); } else { JPEnv::getJava()->ThrowNew(JPJni::s_RuntimeExceptionClass, "Python exception thrown"); } } catch(JavaException*) { cerr << "Java exception at " << __FILE__ << ":" << __LINE__ << endl; } catch(JPypeException* ex) { JPEnv::getJava()->ThrowNew(JPJni::s_RuntimeExceptionClass, ex->getMsg()); } JPEnv::getHost()->prepareCallbackFinish(callbackState); return NULL; TRACE_OUT; }