vector<jobject> getMethods(jclass clazz) { JPCleaner cleaner; jobjectArray methods = (jobjectArray)JPEnv::getJava()->CallObjectMethod(clazz, getMethodsID); cleaner.addLocal(methods); int len = JPEnv::getJava()->GetArrayLength(methods); vector<jobject> res; for (int i = 0; i < len; i++) { jobject c = JPEnv::getJava()->GetObjectArrayElement(methods, i); res.push_back(c); } return res; }
void JPObjectType::setArrayRange(jarray a, int start, int length, vector<HostRef*>& vals) { jobjectArray array = (jobjectArray)a; JPCleaner cleaner; jvalue v; for (int i = 0; i < length; i++) { HostRef* pv = vals[i]; v = convertToJava(pv); cleaner.addLocal(v.l); JPEnv::getJava()->SetObjectArrayElement(array, i+start, v.l); } }
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; }
vector<jclass> getInterfaces(jclass clazz) { JPCleaner cleaner; jobjectArray interfaces = (jobjectArray)JPEnv::getJava()->CallObjectMethod(clazz, getInterfacesID); cleaner.addLocal(interfaces); int len = JPEnv::getJava()->GetArrayLength(interfaces); vector<jclass> res; for (int i = 0; i < len; i++) { jclass c = (jclass)JPEnv::getJava()->GetObjectArrayElement(interfaces, i); res.push_back(c); } return res; }
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; }
void JPProxy::init() { TRACE_IN("JPProxy::init"); // build the proxy class ... jobject cl = JPJni::getSystemClassLoader(); JPCleaner cleaner; jclass handler = JPEnv::getJava()->DefineClass("jpype/JPypeInvocationHandler", cl, JPypeInvocationHandler, getJPypeInvocationHandlerLength()); handlerClass = (jclass)JPEnv::getJava()->NewGlobalRef(handler); cleaner.addLocal(handler); JNINativeMethod method[1]; method[0].name = (char*) "hostInvoke"; method[0].signature =(char*) "(Ljava/lang/String;J[Ljava/lang/Object;[Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/Object;"; method[0].fnPtr = (void*) &Java_jpype_JPypeInvocationHandler_hostInvoke; hostObjectID = JPEnv::getJava()->GetFieldID(handler, "hostObject", "J"); invocationHandlerConstructorID = JPEnv::getJava()->GetMethodID(handler, "<init>", "()V"); JPEnv::getJava()->RegisterNatives(handlerClass, method, 1); // Not quite the right area ... but I;m doing similar here already so let's register the other classes too jclass reference = JPEnv::getJava()->DefineClass("jpype/ref/JPypeReference", cl, JPypeReference, getJPypeReferenceLength()); jclass referenceQueue = JPEnv::getJava()->DefineClass("jpype/ref/JPypeReferenceQueue", cl, JPypeReferenceQueue, getJPypeReferenceQueueLength()); referenceClass = (jclass)JPEnv::getJava()->NewGlobalRef(reference); referenceQueueClass = (jclass)JPEnv::getJava()->NewGlobalRef(referenceQueue); //Required due to bug in jvm //See: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6493522 jmethodID refQConstr = JPEnv::getJava()->GetMethodID(referenceQueue, "<init>", "()V"); cleaner.addLocal(reference); cleaner.addLocal(referenceQueue); JNINativeMethod method2[1]; method2[0].name = (char*) "removeHostReference"; method2[0].signature = (char*) "(J)V"; method2[0].fnPtr = (void*)&Java_jpype_ref_JPypeReferenceQueue_removeHostReference; JPEnv::getJava()->RegisterNatives(referenceQueueClass, method2, 1); TRACE_OUT; }
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; }
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 JPClass::loadSuperClass() { JPCleaner cleaner; // base class .. if any if (!m_IsInterface && m_Name.getSimpleName() != "java.lang.Object") { jclass baseClass = JPEnv::getJava()->GetSuperclass(m_Class); cleaner.addLocal(baseClass); if (baseClass != NULL) { JPTypeName baseClassName = JPJni::getName(baseClass); m_SuperClass = JPTypeManager::findClass(baseClassName); } } }
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; }
void JPClass::loadMethods() { JPCleaner cleaner; JPCleaner pcleaner; // methods vector<jobject> methods = JPJni::getDeclaredMethods(m_Class); cleaner.addAllLocal(methods); for (vector<jobject>::iterator it = methods.begin(); it != methods.end(); it++) { string name = JPJni::getMemberName(*it); if (JPJni::isMemberPublic(*it) && !JPJni::isMemberAbstract(*it) ) { JPMethod* method = getMethod(name); if (method == NULL) { method = new JPMethod(m_Class, name, false); m_Methods[name] = method; } method->addOverload(this, *it); } } // add previous overloads to methods defined in THIS class if (m_SuperClass != NULL) { for (map<string, JPMethod*>::iterator cur = m_Methods.begin(); cur != m_Methods.end(); cur ++) { string name = cur->first; JPMethod* superMethod = m_SuperClass->getMethod(name); if (superMethod != NULL) { cur->second->addOverloads(superMethod); } } } }
void registerRef(jobject refQueue, jobject obj, jlong hostRef) { TRACE_IN("registerRef"); // create the ref ... jvalue args[2]; args[0].l = obj; args[1].l = refQueue; JPCleaner cleaner; jobject refObj = JPEnv::getJava()->NewObjectA(JPypeReferenceClass, JPypeReferenceConstructorMethod, args); cleaner.addLocal(refObj); args[0].l = refObj; args[1].j = hostRef; JPEnv::getJava()->CallVoidMethodA(refQueue, JPypeReferenceQueueRegisterMethod, args); 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; }
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; }
void JPClass::loadFields() { JPCleaner cleaner; // fields vector<jobject> fields = JPJni::getDeclaredFields(m_Class); cleaner.addAllLocal(fields); for (vector<jobject>::iterator it = fields.begin(); it != fields.end(); it++) { JPField* field = new JPField(this, *it); if (field->isStatic()) { m_StaticFields[field->getName()] = field; } else { m_InstanceFields[field->getName()] = field; } } }
PyObject* JPypeModule::synchronized(PyObject* obj, PyObject* args) { JPCleaner cleaner; TRACE_IN("synchronized"); try { PyObject* o; JPyArg::parseTuple(args, "O!", &PyCObject_Type, &o); string desc = (char*)JPyCObject::getDesc(o); jobject obj; if (desc == "JPObject") { JPObject* jpo = (JPObject*)JPyCObject::asVoidPtr(o); obj = jpo->getObject(); cleaner.addLocal(obj); } else if (desc == "JPClass") { JPClass* jpo = (JPClass*)JPyCObject::asVoidPtr(o); obj = jpo->getClass(); cleaner.addLocal(obj); } else if (desc == "JPArray") { JPArray* jpo = (JPArray*)JPyCObject::asVoidPtr(o); obj = jpo->getObject(); cleaner.addLocal(obj); } else if (desc == "JPArrayClass") { JPArrayClass* jpo = (JPArrayClass*)JPyCObject::asVoidPtr(o); obj = jpo->getClass(); cleaner.addLocal(obj); } else if (hostEnv->isWrapper(o) && hostEnv->getWrapperTypeName(o).isObjectType()) { obj = hostEnv->getWrapperValue(o).l; cleaner.addLocal(obj); } // TODO proxy else { RAISE(JPypeException, "method only accepts object values."); } PyJPMonitor* c = PyJPMonitor::alloc(new JPMonitor(obj)); return (PyObject*)c; } PY_STANDARD_CATCH; PyErr_Clear(); Py_INCREF(Py_None); return Py_None; TRACE_OUT; }
string getStackTrace(jthrowable th) { JPCleaner cleaner; jobject strWriter = JPEnv::getJava()->NewObject(stringWriterClass, stringWriterID); cleaner.addLocal(strWriter); jvalue v; v.l = strWriter; jobject printWriter = JPEnv::getJava()->NewObjectA(printWriterClass, printWriterID, &v); cleaner.addLocal(printWriter); v.l = printWriter; JPEnv::getJava()->CallVoidMethodA(th, printStackTraceID, &v); JPEnv::getJava()->CallVoidMethod(printWriter, flushID); jstring res = toString(strWriter); cleaner.addLocal(res); return asciiFromJava(res); }
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* 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; }
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; }
void JPClass::loadConstructors() { JPCleaner cleaner; m_Constructors = new JPMethod(m_Class, "[init", true); if (JPJni::isAbstract(m_Class)) { // NO constructor ... return; } vector<jobject> methods = JPJni::getDeclaredConstructors(m_Class); cleaner.addAllLocal(methods); for (vector<jobject>::iterator it = methods.begin(); it != methods.end(); it++) { if (JPJni::isMemberPublic(*it)) { m_Constructors->addOverload(this, *it); } } }
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; }
static string convertToSimpleName(jclass c) { JPCleaner cleaner; jstring jname = (jstring)JPEnv::getJava()->CallObjectMethod(c, getNameID); cleaner.addLocal(jname); string name = asciiFromJava(jname); // Class.getName returns something weird for arrays ... if (name[0] == '[') { // perform a little cleanup of the name ... unsigned int arrayCount = 0; for (unsigned int i = 0; i < name.length(); i++) { if (name[i] == '[') { arrayCount++; } } name = name.substr(arrayCount, name.length()-(arrayCount)); // Now, let's convert the "native" part switch(name[0]) { case 'B' : name = "byte"; break; case 'S' : name = "short"; break; case 'I' : name = "int"; break; case 'J' : name = "long"; break; case 'F' : name = "float"; break; case 'D' : name = "double"; break; case 'C' : name = "char"; break; case 'Z' : name = "boolean"; break; case 'L' : name = name.substr(1, name.length()-2); for (unsigned int i = 0; i < name.length(); i++) { if (name[i] == '/') { name[i] = '.'; } } break; } for (unsigned int j = 0; j < arrayCount; j++) { name = name + "[]"; } } return name; }
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; }