int pyjfield_set(PyJfield_Object *self, PyObject *value) { JNIEnv *env; jvalue jarg; env = pyembed_get_env(); if(!self) { PyErr_Format(PyExc_RuntimeError, "Invalid self object."); return -1; } if(!self->init) { if(!pyjfield_init(env, self) || PyErr_Occurred()) return -1; } switch(self->fieldTypeId) { case JSTRING_ID: if(!pyarg_matches_jtype(env, value, JSTRING_TYPE, self->fieldTypeId)) { PyErr_Format(PyExc_RuntimeError, "Expected string."); return -1; } jarg = convert_pyarg_jvalue(env, value, JSTRING_TYPE, self->fieldTypeId, 1); if(PyErr_Occurred()) return -1; if(self->isStatic) (*env)->SetStaticObjectField(env, self->pyjobject->clazz, self->fieldId, jarg.l); else (*env)->SetObjectField(env, self->pyjobject->object, self->fieldId, jarg.l); if(process_java_exception(env)) return -1; return 0; // success case JCLASS_ID: if(!pyarg_matches_jtype(env, value, JCLASS_TYPE, self->fieldTypeId)) { PyErr_Format(PyExc_RuntimeError, "Expected class."); return -1; } jarg = convert_pyarg_jvalue(env, value, JCLASS_TYPE, self->fieldTypeId, 1); if(PyErr_Occurred()) return -1; if(self->isStatic) (*env)->SetStaticObjectField(env, self->pyjobject->clazz, self->fieldId, jarg.l); else (*env)->SetObjectField(env, self->pyjobject->object, self->fieldId, jarg.l); if(process_java_exception(env)) return -1; return 0; // success case JOBJECT_ID: if(!pyarg_matches_jtype(env, value, JOBJECT_TYPE, self->fieldTypeId)) { PyErr_Format(PyExc_RuntimeError, "Expected object."); return -1; } jarg = convert_pyarg_jvalue(env, value, JOBJECT_TYPE, self->fieldTypeId, 1); if(PyErr_Occurred()) return -1; if(self->isStatic) (*env)->SetStaticObjectField(env, self->pyjobject->clazz, self->fieldId, jarg.l); else (*env)->SetObjectField(env, self->pyjobject->object, self->fieldId, jarg.l); if(process_java_exception(env)) return -1; return 0; // success case JINT_ID: if(!pyarg_matches_jtype(env, value, JINT_TYPE, self->fieldTypeId)) { PyErr_Format(PyExc_RuntimeError, "Expected int."); return -1; } jarg = convert_pyarg_jvalue(env, value, JINT_TYPE, self->fieldTypeId, 1); if(PyErr_Occurred()) return -1; if(self->isStatic) (*env)->SetStaticIntField(env, self->pyjobject->clazz, self->fieldId, jarg.i); else (*env)->SetIntField(env, self->pyjobject->object, self->fieldId, jarg.i); if(process_java_exception(env)) return -1; return 0; // success case JCHAR_ID: if(!pyarg_matches_jtype(env, value, JCHAR_TYPE, self->fieldTypeId)) { PyErr_Format(PyExc_RuntimeError, "Expected char."); return -1; } jarg = convert_pyarg_jvalue(env, value, JCHAR_TYPE, self->fieldTypeId, 1); if(PyErr_Occurred()) return -1; if(self->isStatic) (*env)->SetStaticCharField(env, self->pyjobject->clazz, self->fieldId, jarg.c); else (*env)->SetCharField(env, self->pyjobject->object, self->fieldId, jarg.c); if(process_java_exception(env)) return -1; return 0; // success case JBYTE_ID: if(!pyarg_matches_jtype(env, value, JBYTE_TYPE, self->fieldTypeId)) { PyErr_Format(PyExc_RuntimeError, "Expected byte."); return -1; } jarg = convert_pyarg_jvalue(env, value, JBYTE_TYPE, self->fieldTypeId, 1); if(PyErr_Occurred()) return -1; if(self->isStatic) (*env)->SetStaticByteField(env, self->pyjobject->clazz, self->fieldId, jarg.b); else (*env)->SetByteField(env, self->pyjobject->object, self->fieldId, jarg.b); if(process_java_exception(env)) return -1; return 0; // success case JSHORT_ID: if(!pyarg_matches_jtype(env, value, JSHORT_TYPE, self->fieldTypeId)) { PyErr_Format(PyExc_RuntimeError, "Expected int."); return -1; } jarg = convert_pyarg_jvalue(env, value, JSHORT_TYPE, self->fieldTypeId, 1); if(PyErr_Occurred()) return -1; if(self->isStatic) (*env)->SetStaticShortField(env, self->pyjobject->clazz, self->fieldId, jarg.s); else (*env)->SetShortField(env, self->pyjobject->object, self->fieldId, jarg.s); if(process_java_exception(env)) return -1; return 0; // success case JDOUBLE_ID: if(!pyarg_matches_jtype(env, value, JDOUBLE_TYPE, self->fieldTypeId)) { PyErr_Format(PyExc_RuntimeError, "Expected float (jdouble)."); return -1; } jarg = convert_pyarg_jvalue(env, value, JDOUBLE_TYPE, self->fieldTypeId, 1); if(PyErr_Occurred()) return -1; if(self->isStatic) (*env)->SetStaticDoubleField(env, self->pyjobject->clazz, self->fieldId, jarg.d); else (*env)->SetDoubleField(env, self->pyjobject->object, self->fieldId, jarg.d); if(process_java_exception(env)) return -1; return 0; // success case JFLOAT_ID: if(!pyarg_matches_jtype(env, value, JFLOAT_TYPE, self->fieldTypeId)) { PyErr_Format(PyExc_RuntimeError, "Expected float (jfloat)."); return -1; } jarg = convert_pyarg_jvalue(env, value, JFLOAT_TYPE, self->fieldTypeId, 1); if(PyErr_Occurred()) return -1; if(self->isStatic) (*env)->SetStaticFloatField(env, self->pyjobject->clazz, self->fieldId, jarg.f); else (*env)->SetFloatField(env, self->pyjobject->object, self->fieldId, jarg.f); if(process_java_exception(env)) return -1; return 0; // success case JLONG_ID: if(!pyarg_matches_jtype(env, value, JLONG_TYPE, self->fieldTypeId)) { PyErr_Format(PyExc_RuntimeError, "Expected long."); return -1; } jarg = convert_pyarg_jvalue(env, value, JLONG_TYPE, self->fieldTypeId, 1); if(PyErr_Occurred()) return -1; if(self->isStatic) (*env)->SetStaticLongField(env, self->pyjobject->clazz, self->fieldId, jarg.j); else (*env)->SetLongField(env, self->pyjobject->object, self->fieldId, jarg.j); if(process_java_exception(env)) return -1; return 0; // success case JBOOLEAN_ID: if(!pyarg_matches_jtype(env, value, JBOOLEAN_TYPE, self->fieldTypeId)) { PyErr_Format(PyExc_RuntimeError, "Expected boolean."); return -1; } jarg = convert_pyarg_jvalue(env, value, JBOOLEAN_TYPE, self->fieldTypeId, 1); if(PyErr_Occurred()) return -1; if(self->isStatic) (*env)->SetStaticBooleanField(env, self->pyjobject->clazz, self->fieldId, jarg.z); else (*env)->SetBooleanField(env, self->pyjobject->object, self->fieldId, jarg.z); if(process_java_exception(env)) return -1; return 0; // success } PyErr_Format(PyExc_RuntimeError, "Unknown field type %i.", self->fieldTypeId); return -1; }
// find and call a method on this object that matches the python args. // typically called by way of pyjmethod when python invokes __call__. // // steals reference to self, methodname and args. PyObject* find_method(JNIEnv *env, PyObject *methodName, Py_ssize_t methodCount, PyObject *attr, PyObject *args) { // all possible method candidates PyJmethod_Object **cand = NULL; Py_ssize_t pos, i, listSize, argsSize; pos = i = listSize = argsSize = 0; // not really likely if we were called from pyjmethod, but hey... if(methodCount < 1) { PyErr_Format(PyExc_RuntimeError, "I have no methods."); return NULL; } if(!attr || !PyList_CheckExact(attr)) { PyErr_Format(PyExc_RuntimeError, "Invalid attr list."); return NULL; } cand = (PyJmethod_Object **) PyMem_Malloc(sizeof(PyJmethod_Object*) * methodCount); // just for safety for(i = 0; i < methodCount; i++) cand[i] = NULL; listSize = PyList_GET_SIZE(attr); for(i = 0; i < listSize; i++) { PyObject *tuple = PyList_GetItem(attr, i); /* borrowed */ if(PyErr_Occurred()) break; if(!tuple || tuple == Py_None || !PyTuple_CheckExact(tuple)) continue; if(PyTuple_Size(tuple) == 2) { PyObject *key = PyTuple_GetItem(tuple, 0); /* borrowed */ if(PyErr_Occurred()) break; if(!key || !PyString_Check(key)) continue; if(PyObject_Compare(key, methodName) == 0) { PyObject *method = PyTuple_GetItem(tuple, 1); /* borrowed */ if(pyjmethod_check(method)) cand[pos++] = (PyJmethod_Object *) method; } } } if(PyErr_Occurred()) goto EXIT_ERROR; // makes more sense to work with... pos--; if(pos < 0) { // didn't find a method by that name.... // that shouldn't happen unless the search above is broken. PyErr_Format(PyExc_NameError, "No such method."); goto EXIT_ERROR; } if(pos == 0) { // we're done, call that one PyObject *ret = pyjmethod_call_internal(cand[0], args); PyMem_Free(cand); return ret; } // first, find out if there's only one method that // has the correct number of args argsSize = PyTuple_Size(args); { PyJmethod_Object *matching = NULL; int count = 0; for(i = 0; i <= pos && cand[i]; i++) { // make sure method is fully initialized if(!cand[i]->parameters) { if(!pyjmethod_init(env, cand[i])) { // init failed, that's not good. cand[i] = NULL; PyErr_Warn(PyExc_Warning, "pyjmethod init failed."); continue; } } if(cand[i]->lenParameters == argsSize) { matching = cand[i]; count++; } else cand[i] = NULL; // eliminate non-matching } if(matching && count == 1) { PyMem_Free(cand); return pyjmethod_call_internal(matching, args); } } // local scope for(i = 0; i <= pos; i++) { int parmpos = 0; // already eliminated? if(!cand[i]) continue; // check if argument types match (*env)->PushLocalFrame(env, 20); for(parmpos = 0; parmpos < cand[i]->lenParameters; parmpos++) { PyObject *param = PyTuple_GetItem(args, parmpos); int paramTypeId = -1; jclass pclazz; jclass paramType = (jclass) (*env)->GetObjectArrayElement(env, cand[i]->parameters, parmpos); if(process_java_exception(env) || !paramType) break; pclazz = (*env)->GetObjectClass(env, paramType); if(process_java_exception(env) || !pclazz) break; paramTypeId = get_jtype(env, paramType, pclazz); if(pyarg_matches_jtype(env, param, paramType, paramTypeId)) { if(PyErr_Occurred()) break; continue; } // args don't match break; } (*env)->PopLocalFrame(env, NULL); // this method matches? if(parmpos == cand[i]->lenParameters) { PyObject *ret = pyjmethod_call_internal(cand[i], args); PyMem_Free(cand); return ret; } } EXIT_ERROR: PyMem_Free(cand); if(!PyErr_Occurred()) PyErr_Format(PyExc_NameError, "Matching overloaded method not found."); return NULL; }