HostRef* PythonHostEnvironment::getCallableFrom(HostRef* ref, string& name) { JPCleaner cleaner; PyObject* pname = JPyString::fromString(name.c_str()); cleaner.add(new HostRef(pname, false)); PyObject* mname = JPyString::fromString("getCallable"); cleaner.add(new HostRef(mname, false)); PyObject* call = PyObject_CallMethodObjArgs(UNWRAP(ref), mname, pname, NULL); JPyErr::check(); return new HostRef(call, false); }
PyObject* PyJPMethod::__call__(PyObject* o, PyObject* args, PyObject* kwargs) { TRACE_IN("PyJPMethod::__call__"); try { PyJPMethod* self = (PyJPMethod*)o; TRACE1(self->m_Method->getName()); JPCleaner cleaner; //JPyHelper::dumpSequenceRefs(args, "start"); vector<HostRef*> vargs; Py_ssize_t len = JPyObject::length(args); for (Py_ssize_t i = 0; i < len; i++) { PyObject* obj = JPySequence::getItem(args, i); // return a new ref HostRef* ref = new HostRef((void*)obj); cleaner.add(ref); vargs.push_back(ref); Py_DECREF(obj); // delete the new ref returned by getItem } //JPyHelper::dumpSequenceRefs(args, "middle"); HostRef* res = self->m_Method->invoke(vargs); //JPyHelper::dumpSequenceRefs(args, "end"); return detachRef(res); } PY_STANDARD_CATCH return NULL; TRACE_OUT; }
PyObject* PyJPMethod::matchReport(PyObject* o, PyObject* args) { try { PyJPMethod* self = (PyJPMethod*)o; JPCleaner cleaner; vector<HostRef*> vargs; Py_ssize_t len = JPyObject::length(args); for (Py_ssize_t i = 0; i < len; i++) { PyObject* obj = JPySequence::getItem(args, i); HostRef* ref = new HostRef((void*)obj); cleaner.add(ref); vargs.push_back(ref); Py_DECREF(obj); } string report = self->m_Method->matchReport(vargs); PyObject* res = JPyString::fromString(report.c_str()); return res; } PY_STANDARD_CATCH return NULL; }
void JPypeJavaException::errorOccurred() { TRACE_IN("PyJavaException::errorOccurred"); JPCleaner cleaner; jthrowable th = JPEnv::getJava()->ExceptionOccurred(); cleaner.addLocal(th); JPEnv::getJava()->ExceptionClear(); jclass ec = JPJni::getClass(th); JPTypeName tn = JPJni::getName(ec); JPClass* jpclass = JPTypeManager::findClass(tn); cleaner.addLocal(ec); PyObject* jexclass = hostEnv->getJavaShadowClass(jpclass); HostRef* pyth = hostEnv->newObject(new JPObject(tn, th)); cleaner.add(pyth); PyObject* args = JPySequence::newTuple(2); PyObject* arg2 = JPySequence::newTuple(1); JPySequence::setItem(arg2, 0, args); Py_DECREF(args); JPySequence::setItem(args, 0, hostEnv->m_SpecialConstructorKey); JPySequence::setItem(args, 1, (PyObject*)pyth->data()); PyObject* pyexclass = JPyObject::getAttrString(jexclass, "PYEXC"); Py_DECREF(jexclass); JPyErr::setObject(pyexclass, arg2); Py_DECREF(arg2); Py_DECREF(pyexclass); TRACE_OUT; }
PyObject* PyJPField::setInstanceAttribute(PyObject* o, PyObject* arg) { JPCleaner cleaner; try { PyJPField* self = (PyJPField*)o; PyObject* jo; PyObject* value; JPyArg::parseTuple(arg, "O!O", &PyCapsule_Type, &jo, &value); JPObject* obj = (JPObject*)JPyCObject::asVoidPtr(jo); HostRef* ref = new HostRef(value); cleaner.add(ref); jobject jobj = obj->getObject(); cleaner.addLocal(jobj); self->m_Field->setAttribute(jobj, ref); Py_INCREF(Py_None); return Py_None; } PY_STANDARD_CATCH return NULL; }
JPProxy* PythonHostEnvironment::asProxy(HostRef* ref) { JPCleaner cleaner; PyObject* proxy = UNWRAP(ref); PyObject* jproxy = JPyObject::getAttrString(proxy, "_proxy"); cleaner.add(new HostRef(jproxy, false)); JPProxy* res = (JPProxy*)JPyCObject::asVoidPtr(jproxy); return res; }
EMatchType JPArrayClass::canConvertToJava(HostRef* o) { JPCleaner cleaner; if (JPEnv::getHost()->isNone(o)) { return _implicit; } if (JPEnv::getHost()->isArray(o)) { JPArray* a = JPEnv::getHost()->asArray(o); JPArrayClass* ca = a->getClass(); if (ca == this) { return _exact; } if (JPEnv::getJava()->IsAssignableFrom(ca->m_Class, m_Class)) { return _implicit; } } else if (JPEnv::getHost()->isUnicodeString(o) && m_ComponentType->getName().getType() ==JPTypeName::_char) { // Strings are also char[] return _implicit; } else if (JPEnv::getHost()->isByteString(o) && m_ComponentType->getName().getType() ==JPTypeName::_byte) { // Strings are also char[] return _implicit; } else if (JPEnv::getHost()->isSequence(o)) { EMatchType match = _implicit; int length = JPEnv::getHost()->getSequenceLength(o); for (int i = 0; i < length && match > _none; i++) { HostRef* obj = JPEnv::getHost()->getSequenceItem(o, i); cleaner.add(obj); EMatchType newMatch = m_ComponentType->canConvertToJava(obj); if (newMatch < match) { match = newMatch; } } return match; } return _none; }
PyObject* JPypeJavaArray::setArraySlice(PyObject* self, PyObject* arg) { TRACE_IN("JPypeJavaArray::setArraySlice") PyObject* arrayObject; int lo = -1; int hi = -1; PyObject* sequence; try { JPyArg::parseTuple(arg, "O!iiO", &PyCapsule_Type, &arrayObject, &lo, &hi, &sequence); JPArray* a = (JPArray*)JPyCObject::asVoidPtr(arrayObject); int length = a->getLength(); if(length == 0) Py_RETURN_NONE; if (lo < 0) lo = length + lo; if (lo < 0) lo = 0; else if (lo > length) lo = length; if (hi < 0) hi = length + hi; if (hi < 0) hi = 0; else if (hi > length) hi = length; if (lo > hi) lo = hi; const JPTypeName& componentName = a->getType()->getObjectType().getComponentName(); const string& name = componentName.getNativeName(); if(is_primitive(name[0])) { // for primitive types, we have fast setters available a->setRange(lo, hi, sequence); } else { // slow wrapped access for non primitive types vector<HostRef*> values; values.reserve(hi - lo); JPCleaner cleaner; for (Py_ssize_t i = 0; i < hi - lo; i++) { HostRef* v = new HostRef(JPySequence::getItem(sequence, i), false); values.push_back(v); cleaner.add(v); } a->setRange(lo, hi, values); } Py_RETURN_NONE; } PY_STANDARD_CATCH return NULL; TRACE_OUT }
PyObject* PyJPBoundMethod::__call__(PyObject* o, PyObject* args, PyObject* kwargs) { TRACE_IN("PyJPBoundMethod::__call__"); try { PyObject* result=NULL; { PyJPBoundMethod* self = (PyJPBoundMethod*)o; JPCleaner cleaner; TRACE1(self->m_Method->m_Method->getName()); vector<HostRef*> vargs; Py_ssize_t len = JPyObject::length(args); HostRef* ref = new HostRef((void*)self->m_Instance); cleaner.add(ref); vargs.push_back(ref); for (Py_ssize_t i = 0; i < len; i++) { PyObject* obj = JPySequence::getItem(args, i); // returns a new ref ref = new HostRef((void*)obj); cleaner.add(ref); vargs.push_back(ref); Py_DECREF(obj); // remove ref returned by getItem } HostRef* res = self->m_Method->m_Method->invoke(vargs); TRACE2("Call finished, result = ", res); result = detachRef(res); TRACE1("Cleaning up"); } return result; } PY_STANDARD_CATCH return NULL; TRACE_OUT; }
HostRef* PythonHostEnvironment::callObject(HostRef* c, vector<HostRef*>& args) { JPCleaner cleaner; PyObject* pargs = JPySequence::newTuple((int)args.size()); cleaner.add(new HostRef(pargs, false)); for (unsigned int i = 0; i < args.size(); i++) { JPySequence::setItem(pargs, i, UNWRAP(args[i])); } PyObject* res = JPyObject::call(UNWRAP(c), pargs, NULL); return new HostRef(res, false); }
PyObject* JPypeJavaArray::getArraySlice(PyObject* self, PyObject* arg) { PyObject* arrayObject; int lo = -1; int hi = -1; try { JPyArg::parseTuple(arg, "O!ii", &PyCapsule_Type, &arrayObject, &lo, &hi); JPArray* a = (JPArray*)JPyCObject::asVoidPtr(arrayObject); int length = a->getLength(); // stolen from jcc, to get nice slice support if (lo < 0) lo = length + lo; if (lo < 0) lo = 0; else if (lo > length) lo = length; if (hi < 0) hi = length + hi; if (hi < 0) hi = 0; else if (hi > length) hi = length; if (lo > hi) lo = hi; const JPTypeName& componentName = a->getType()->getObjectType().getComponentName(); const string& name = componentName.getNativeName(); if(is_primitive(name[0])) { // for primitive types, we have fast sequence generation available return a->getSequenceFromRange(lo, hi); } else { // slow wrapped access for non primitives vector<HostRef*> values = a->getRange(lo, hi); JPCleaner cleaner; PyObject* res = JPySequence::newList((int)values.size()); for (unsigned int i = 0; i < values.size(); i++) { JPySequence::setItem(res, i, (PyObject*)values[i]->data()); cleaner.add(values[i]); } return res; } } PY_STANDARD_CATCH return NULL; }
PyObject* JPypeJavaArray::setArrayItem(PyObject* self, PyObject* arg) { try { PyObject* arrayObject; int ndx; PyObject* value; JPyArg::parseTuple(arg, "O!iO", &PyCObject_Type, &arrayObject, &ndx, &value); JPArray* a = (JPArray*)JPyCObject::asVoidPtr(arrayObject); JPCleaner cleaner; HostRef* v = new HostRef(value); cleaner.add(v); a->setItem(ndx, v); Py_RETURN_NONE; } PY_STANDARD_CATCH return NULL; }
PyObject* JPypeJavaProxy::createProxy(PyObject*, PyObject* arg) { try { JPCleaner cleaner; PyObject* self; PyObject* intf; //TODO: why is self not initialized? JPyArg::parseTuple(arg, "OO", &self, &intf); std::vector<jclass> interfaces; Py_ssize_t len = JPyObject::length(intf); for (Py_ssize_t i = 0; i < len; i++) { PyObject* subObj = JPySequence::getItem(intf, i); cleaner.add(new HostRef(subObj, false)); PyObject* claz = JPyObject::getAttrString(subObj, "__javaclass__"); PyJPClass* c = (PyJPClass*)claz; jclass jc = c->m_Class->getClass(); cleaner.addGlobal(jc); interfaces.push_back(jc); } HostRef ref = HostRef(self); JPProxy* proxy = new JPProxy(&ref, interfaces); PyObject* res = JPyCObject::fromVoidAndDesc(proxy, (void*)"jproxy", PythonHostEnvironment::deleteJPProxyDestructor); return res; } PY_STANDARD_CATCH return NULL; }
jvalue JPArrayClass::convertToJava(HostRef* obj) { JPCleaner cleaner; jvalue res; res.l = NULL; if (JPEnv::getHost()->isArray(obj)) { JPArray* a = JPEnv::getHost()->asArray(obj); res = a->getValue(); } else if (JPEnv::getHost()->isByteString(obj) && m_ComponentType->getName().getType() == JPTypeName::_byte && sizeof(char) == sizeof(jbyte)) { char* rawData; long size; JPEnv::getHost()->getRawByteString(obj, &rawData, size); jbyteArray array = JPEnv::getJava()->NewByteArray(size); cleaner.addLocal(array); res.l = array; jboolean isCopy; jbyte* contents = JPEnv::getJava()->GetByteArrayElements(array, &isCopy); memcpy(contents, rawData, size*sizeof(jbyte)); JPEnv::getJava()->ReleaseByteArrayElements(array, contents, 0); cleaner.removeLocal(array); } else if (JPEnv::getHost()->isUnicodeString(obj) && m_ComponentType->getName().getType() == JPTypeName::_char && JPEnv::getHost()->getUnicodeSize() == sizeof(jchar)) { jchar* rawData; long size; JPEnv::getHost()->getRawUnicodeString(obj, &rawData, size); jcharArray array = JPEnv::getJava()->NewCharArray(size); cleaner.addLocal(array); res.l = array; jboolean isCopy; jchar* contents = JPEnv::getJava()->GetCharArrayElements(array, &isCopy); memcpy(contents, rawData, size*sizeof(jchar)); JPEnv::getJava()->ReleaseCharArrayElements(array, contents, 0); cleaner.removeLocal(array); } else if (JPEnv::getHost()->isSequence(obj)) { int length = JPEnv::getHost()->getSequenceLength(obj); jarray array = m_ComponentType->newArrayInstance(length); cleaner.addLocal(array); res.l = array; for (int i = 0; i < length ; i++) { HostRef* obj2 = JPEnv::getHost()->getSequenceItem(obj, i); cleaner.add(obj2); m_ComponentType->setArrayItem(array, i, obj2); } cleaner.removeLocal(array); } return res; }
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; }