void JPField::setStaticAttribute(HostRef* val) { TRACE_IN("JPField::setStaticAttribute"); if (m_IsFinal) { stringstream err; err << "Field " << m_Name << " is read-only"; RAISE(JPypeException, err.str().c_str()); } JPType* type = JPTypeManager::getType(m_Type); if (type->canConvertToJava(val) <= _explicit) { stringstream err; err << "unable to convert to " << type->getName().getSimpleName(); RAISE(JPypeException, err.str().c_str()); } JPCleaner cleaner; jclass claz = m_Class->getClass(); cleaner.addLocal(claz); type->setStaticValue(claz, m_FieldID, val); TRACE_OUT; }
PyObject* JPypeJavaNio::convertToDirectBuffer(PyObject* self, PyObject* args) { TRACE_IN("convertStringToBuffer"); // Use special method defined on the TypeConverter interface ... PyObject* src; JPyArg::parseTuple(args, "O", &src); PyObject* res = NULL; if (JPyObject::isMemoryView(src)) { // converts to byte buffer ... JPTypeName tname = JPTypeName::fromType(JPTypeName::_byte); JPType* type = JPTypeManager::getType(tname); HostRef srcRef(src); TRACE1("Converting"); HostRef* ref = type->convertToDirectBuffer(&srcRef); JPEnv::registerRef(ref, &srcRef); TRACE1("detaching result"); res = detachRef(ref); } if (res != NULL) { return res; } RAISE(JPypeException, "Do not know how to convert to direct byte buffer, only memory view supported"); return NULL; TRACE_OUT; }
void JPArray::setRange(int start, int stop, vector<HostRef*>& val) { JPCleaner cleaner; JPType* compType = m_Class->getComponentType(); if(stop < start) { std::stringstream out; out << "Slice start (" << start << ") is greater than stop (" << stop << ")"; RAISE(JPypeException, out.str()); } unsigned int len = stop-start; size_t plength = val.size(); if (len != plength) { std::stringstream out; out << "Slice assignment must be of equal lengths : " << len << " != " << plength; RAISE(JPypeException, out.str()); } for (size_t i = 0; i < plength; i++) { HostRef* v = val[i]; if ( compType->canConvertToJava(v)<= _explicit) { RAISE(JPypeException, "Unable to convert."); } } compType->setArrayRange(m_Object, start, stop-start, val); }
PyObject* convertToJValue(PyObject* self, PyObject* arg) { try { char* tname; PyObject* value; JPyArg::parseTuple(arg, "sO", &tname, &value); JPTypeName name = JPTypeName::fromSimple(tname); JPType* type = JPTypeManager::getType(name); HostRef ref(value); jvalue v = type->convertToJava(&ref); jvalue* pv = new jvalue(); *pv = v; PyObject* res; if (type->isObjectType()) { res = JPyCObject::fromVoidAndDesc((void*)pv, (void*)"object jvalue", PythonHostEnvironment::deleteObjectJValueDestructor); } else { res = JPyCObject::fromVoidAndDesc((void*)pv, (void*)"jvalue", PythonHostEnvironment::deleteJValueDestructor); } return res; } PY_STANDARD_CATCH return NULL; }
JPObject* JPMethodOverload::invokeConstructor(jclass claz, vector<HostRef*>& arg) { TRACE_IN("JPMethodOverload::invokeConstructor"); size_t len = arg.size(); JPCleaner cleaner; JPMallocCleaner<jvalue> v(len); for (unsigned int i = 0; i < len; i++) { HostRef* obj = arg[i]; // TODO the following can easily be optimized ... or at least cached JPType* t = JPTypeManager::getType(m_Arguments[i]); v[i] = t->convertToJava(obj); if (t->isObjectType()) { cleaner.addLocal(v[i].l); } } jvalue val; val.l = JPEnv::getJava()->NewObjectA(claz, m_MethodID, v.borrow()); cleaner.addLocal(val.l); TRACE1("Object created"); JPTypeName name = JPJni::getName(claz); return new JPObject(name, val.l); TRACE_OUT; }
HostRef* JPMethodOverload::invokeStatic(vector<HostRef*>& arg) { TRACE_IN("JPMethodOverload::invokeStatic"); JPCleaner cleaner; size_t len = arg.size(); JPMallocCleaner<jvalue> v(len); JPMallocCleaner<JPType*> types(len); for (unsigned int i = 0; i < len; i++) { HostRef* obj = arg[i]; types[i] = JPTypeManager::getType(m_Arguments[i]); v[i] = types[i]->convertToJava(obj); if (types[i]->isObjectType()) { cleaner.addLocal(v[i].l); } } jclass claz = m_Class->getClass(); cleaner.addGlobal(claz); JPType* retType = JPTypeManager::getType(m_ReturnType); return retType->invokeStatic(claz, m_MethodID, v.borrow()); TRACE_OUT; }
PyObject* JPArray::getSequenceFromRange(int start, int stop) { // TRACE_IN("JPArray::getSequenceFromRange"); JPType* compType = m_Class->getComponentType(); // TRACE2("Component type", compType->getName().getSimpleName()); return compType->getArrayRangeToSequence(m_Object, start, stop); }
HostRef* JPField::getAttribute(jobject inst) { TRACE_IN("JPField::getAttribute"); TRACE2("field type", m_Type.getSimpleName()); JPType* type = JPTypeManager::getType(m_Type); return type->getInstanceValue(inst, m_FieldID, m_Type); TRACE_OUT; }
void JPArray::setItem(int ndx, HostRef* val) { JPType* compType = m_Class->getComponentType(); if (compType->canConvertToJava(val) <= _explicit) { RAISE(JPypeException, "Unable to convert."); } compType->setArrayItem(m_Object, ndx, val); }
vector<HostRef*> JPArray::getRange(int start, int stop) { TRACE_IN("JPArray::getRange"); JPType* compType = m_Class->getComponentType(); TRACE2("Component type", compType->getName().getSimpleName()); vector<HostRef*> res = compType->getArrayRange(m_Object, start, stop-start); return res; TRACE_OUT; }
HostRef* JPField::getStaticAttribute() { TRACE_IN("JPField::getStaticAttribute"); JPType* type = JPTypeManager::getType(m_Type); JPCleaner cleaner; jclass claz = m_Class->getClass(); cleaner.addLocal(claz); return type->getStaticValue(claz, m_FieldID, m_Type); TRACE_OUT; }
HostRef* JPObjectType::getInstanceValue(jobject c, jfieldID fid, JPTypeName& tgtType) { TRACE_IN("JPObjectType::getInstanceValue"); JPCleaner cleaner; jobject r = JPEnv::getJava()->GetObjectField(c, fid); cleaner.addLocal(r); jvalue v; v.l = r; JPTypeName name = JPJni::getClassName(v.l); JPType* type = JPTypeManager::getType(name); return type->asHostObject(v); TRACE_OUT; }
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; }
HostRef* JPObjectType::invokeStatic(jclass claz, jmethodID mth, jvalue* val) { TRACE_IN("JPObjectType::invokeStatic"); JPCleaner cleaner; jobject res = JPEnv::getJava()->CallStaticObjectMethodA(claz, mth, val); cleaner.addLocal(res); jvalue v; v.l = res; JPTypeName name = JPJni::getClassName(v.l); JPType* type = JPTypeManager::getType(name); return type->asHostObject(v); TRACE_OUT; }
void JPArray::setRange(int start, int stop, PyObject* sequence) { JPType* compType = m_Class->getComponentType(); unsigned int len = stop-start; // check bounds of sequence which is to be assigned HostRef* ptr = new HostRef(sequence); unsigned int plength = JPEnv::getHost()->getSequenceLength(ptr); delete ptr; if (len != plength) { std::stringstream out; out << "Slice assignment must be of equal lengths : " << len << " != " << plength; RAISE(JPypeException, out.str()); } compType->setArrayRange(m_Object, start, len, sequence); }
HostRef* JPClass::asHostObject(jvalue obj) { TRACE_IN("JPClass::asPyObject"); if (obj.l == NULL) { return JPEnv::getHost()->getNone(); } JPTypeName name = JPJni::getClassName(obj.l); if (name.getType() ==JPTypeName::_array) { JPType* arrayType = JPTypeManager::getType(name); return arrayType->asHostObject(obj); } return JPEnv::getHost()->newObject(new JPObject(name, obj.l)); TRACE_OUT; }
HostRef* JPObjectType::invoke(jobject claz, jclass clazz, jmethodID mth, jvalue* val) { TRACE_IN("JPObjectType::invoke"); JPCleaner cleaner; jobject res = JPEnv::getJava()->CallNonvirtualObjectMethodA(claz, clazz, mth, val); cleaner.addLocal(res); jvalue v; v.l = res; JPTypeName name = JPJni::getClassName(v.l); JPType* type = JPTypeManager::getType(name); HostRef* ref = type->asHostObject(v); TRACE1("Successfulyl converted to host reference"); return ref; TRACE_OUT; }
void JPField::setAttribute(jobject inst, HostRef* val) { TRACE_IN("JPField::setAttribute"); if (m_IsFinal) { stringstream err; err << "Field " << m_Name << " is read-only"; RAISE(JPypeException, err.str().c_str()); } JPType* type = JPTypeManager::getType(m_Type); if (type->canConvertToJava(val) <= _explicit) { stringstream err; err << "unable to convert to " << type->getName().getSimpleName(); RAISE(JPypeException, err.str().c_str()); } type->setInstanceValue(inst, m_FieldID, val); TRACE_OUT; }
HostRef* JPObjectType::getArrayItem(jarray a, int ndx) { TRACE_IN("JPObjectType::getArrayItem"); jobjectArray array = (jobjectArray)a; JPCleaner cleaner; jobject obj = JPEnv::getJava()->GetObjectArrayElement(array, ndx); cleaner.addLocal(obj); if (obj == NULL) { return JPEnv::getHost()->getNone(); } jvalue v; v.l = obj; JPTypeName name = JPJni::getClassName(v.l); JPType* t = JPTypeManager::getType(name); return t->asHostObject(v); TRACE_OUT; }
vector<HostRef*> JPObjectType::getArrayRange(jarray a, int start, int length) { jobjectArray array = (jobjectArray)a; JPCleaner cleaner; vector<HostRef*> res; jvalue v; for (int i = 0; i < length; i++) { v.l = JPEnv::getJava()->GetObjectArrayElement(array, i+start); cleaner.addLocal(v.l); JPTypeName name = JPJni::getClassName(v.l); JPType* t = JPTypeManager::getType(name); HostRef* pv = t->asHostObject(v); res.push_back(pv); } return res; }
EMatchType JPMethodOverload::matches(bool ignoreFirst, vector<HostRef*>& arg) { TRACE_IN("JPMethodOverload::matches"); size_t len = arg.size(); if (len != m_Arguments.size()) { return _none; } EMatchType lastMatch = _exact; for (unsigned int i = 0; i < len; i++) { if (i == 0 && ignoreFirst) { continue; } HostRef* obj = arg[i]; JPType* type = JPTypeManager::getType(m_Arguments[i]); EMatchType match = type->canConvertToJava(obj); if (match < _implicit) { return _none; } if (match < lastMatch) { lastMatch = match; } } return lastMatch; TRACE_OUT; }
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; }
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; }
HostRef* JPArray::getItem(int ndx) { JPType* compType = m_Class->getComponentType(); return compType->getArrayItem(m_Object, ndx); }