/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "java/lang/Object.h" #include "java/lang/Class.h" #include "java/lang/String.h" #include "java/lang/Throwable.h" #include "java/lang/Boolean.h" #include "java/lang/Integer.h" #include "java/lang/Long.h" #include "java/lang/Double.h" #include "java/util/Iterator.h" #include "JArray.h" #include "functions.h" #include "macros.h" using namespace java::lang; using namespace java::util; PyObject *PyExc_JavaError = PyExc_ValueError; PyObject *PyExc_InvalidArgsError = PyExc_ValueError; PyObject *_set_exception_types(PyObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, "OO", &PyExc_JavaError, &PyExc_InvalidArgsError)) return NULL; Py_RETURN_NONE; } PyObject *_set_function_self(PyObject *self, PyObject *args) { PyObject *object, *module; if (!PyArg_ParseTuple(args, "OO", &object, &module)) return NULL; if (!PyCFunction_Check(object)) { PyErr_SetObject(PyExc_TypeError, object); return NULL; } PyCFunctionObject *cfn = (PyCFunctionObject *) object; Py_INCREF(module); Py_XDECREF(cfn->m_self); cfn->m_self = module; Py_RETURN_NONE; } PyObject *findClass(PyObject *self, PyObject *args) { char *className; if (!PyArg_ParseTuple(args, "s", &className)) return NULL; try { jclass cls = env->findClass(className); if (cls) return t_Class::wrap_Object(Class(cls)); } catch (JCCEnv::pythonError e) { return NULL; } catch (JCCEnv::exception e) { PyErr_SetJavaError(e.throwable); return NULL; } Py_RETURN_NONE; } #if defined(_MSC_VER) || defined(__SUNPRO_CC) int __parseArgs(PyObject *args, char *types, ...) { int count = ((PyTupleObject *)(args))->ob_size; va_list list, check; va_start(list, types); va_start(check, types); return _parseArgs(((PyTupleObject *)(args))->ob_item, count, types, list, check); } int __parseArg(PyObject *arg, char *types, ...) { va_list list, check; va_start(list, types); va_start(check, types); return _parseArgs(&arg, 1, types, list, check); } int _parseArgs(PyObject **args, unsigned int count, char *types, va_list list, va_list check) { unsigned int typeCount = strlen(types); if (count > typeCount) return -1; #else int _parseArgs(PyObject **args, unsigned int count, char *types, ...) { unsigned int typeCount = strlen(types); va_list list, check; if (count > typeCount) return -1; va_start(list, types); va_start(check, types); #endif if (!env->vm) { PyErr_SetString(PyExc_RuntimeError, "initVM() must be called first"); return -1; } JNIEnv *vm_env = env->get_vm_env(); if (!vm_env) { PyErr_SetString(PyExc_RuntimeError, "attachCurrentThread() must be called first"); return -1; } unsigned int pos = 0; int array = 0; for (unsigned int a = 0; a < count; a++, pos++) { PyObject *arg = args[a]; switch (types[pos]) { case '[': { if (++array > 1) return -1; a -= 1; break; } case 'j': /* Java object, with class$ */ case 'k': /* Java object, with initializeClass */ case 'K': /* Java object, with initializeClass and params */ { jclass cls = NULL; switch (types[pos]) { case 'j': cls = (jclass) va_arg(list, Class *)->this$; break; case 'k': case 'K': try { getclassfn initializeClass = va_arg(list, getclassfn); cls = (*initializeClass)(); } catch (JCCEnv::pythonError e) { return -1; } catch (JCCEnv::exception e) { PyErr_SetJavaError(e.throwable); return -1; } break; } if (arg == Py_None) break; /* ensure that class Class is initialized (which may not be the * case because of earlier recursion avoidance (JObject(cls)). */ if (!Class::class$) Class::initializeClass(); if (array) { if (PyObject_TypeCheck(arg, JArrayObject$$Type)) break; if (PySequence_Check(arg) && !PyString_Check(arg) && !PyUnicode_Check(arg)) { if (PySequence_Length(arg) > 0) { PyObject *obj = PySequence_GetItem(arg, 0); int ok = 0; if (obj == Py_None) ok = 1; else if (PyObject_TypeCheck(obj, &Object$$Type) && vm_env->IsInstanceOf(((t_Object *) obj)->object.this$, cls)) ok = 1; else if (PyObject_TypeCheck(obj, &FinalizerProxy$$Type)) { PyObject *o = ((t_fp *) obj)->object; if (PyObject_TypeCheck(o, &Object$$Type) && vm_env->IsInstanceOf(((t_Object *) o)->object.this$, cls)) ok = 1; } Py_DECREF(obj); if (ok) break; } else break; } } else if (PyObject_TypeCheck(arg, &Object$$Type) && vm_env->IsInstanceOf(((t_Object *) arg)->object.this$, cls)) break; else if (PyObject_TypeCheck(arg, &FinalizerProxy$$Type)) { arg = ((t_fp *) arg)->object; if (PyObject_TypeCheck(arg, &Object$$Type) && vm_env->IsInstanceOf(((t_Object *) arg)->object.this$, cls)) break; } return -1; } case 'Z': /* boolean, strict */ { if (array) { if (arg == Py_None) break; if (PyObject_TypeCheck(arg, JArrayBool$$Type)) break; if (PySequence_Check(arg)) { if (PySequence_Length(arg) > 0) { PyObject *obj = PySequence_GetItem(arg, 0); int ok = obj == Py_True || obj == Py_False; Py_DECREF(obj); if (ok) break; } else break; } } else if (arg == Py_True || arg == Py_False) break; return -1; } case 'B': /* byte */ { if (array) { if (arg == Py_None) break; if (PyObject_TypeCheck(arg, JArrayByte$$Type)) break; } else if (PyString_Check(arg) && (PyString_Size(arg) == 1)) break; else if (PyInt_CheckExact(arg)) break; return -1; } case 'C': /* char */ { if (array) { if (arg == Py_None) break; if (PyObject_TypeCheck(arg, JArrayChar$$Type)) break; } else if (PyUnicode_Check(arg) && PyUnicode_GET_SIZE(arg) == 1) break; return -1; } case 'I': /* int */ { if (array) { if (arg == Py_None) break; if (PyObject_TypeCheck(arg, JArrayInt$$Type)) break; if (PySequence_Check(arg)) { if (PySequence_Length(arg) > 0) { PyObject *obj = PySequence_GetItem(arg, 0); int ok = PyInt_CheckExact(obj); Py_DECREF(obj); if (ok) break; } else break; } } else if (PyInt_CheckExact(arg)) break; return -1; } case 'S': /* short */ { if (array) { if (arg == Py_None) break; if (PyObject_TypeCheck(arg, JArrayShort$$Type)) break; if (PySequence_Check(arg)) { if (PySequence_Length(arg) > 0) { PyObject *obj = PySequence_GetItem(arg, 0); int ok = PyInt_CheckExact(obj); Py_DECREF(obj); if (ok) break; } else break; } } else if (PyInt_CheckExact(arg)) break; return -1; } case 'D': /* double */ { if (array) { if (arg == Py_None) break; if (PyObject_TypeCheck(arg, JArrayDouble$$Type)) break; if (PySequence_Check(arg)) { if (PySequence_Length(arg) > 0) { PyObject *obj = PySequence_GetItem(arg, 0); int ok = PyFloat_CheckExact(obj); Py_DECREF(obj); if (ok) break; } else break; } } else if (PyFloat_CheckExact(arg)) break; return -1; } case 'F': /* float */ { if (array) { if (arg == Py_None) break; if (PyObject_TypeCheck(arg, JArrayFloat$$Type)) break; if (PySequence_Check(arg)) { if (PySequence_Length(arg) > 0) { PyObject *obj = PySequence_GetItem(arg, 0); int ok = PyFloat_CheckExact(obj); Py_DECREF(obj); if (ok) break; } else break; } } else if (PyFloat_CheckExact(arg)) break; return -1; } case 'J': /* long long */ { if (array) { if (arg == Py_None) break; if (PyObject_TypeCheck(arg, JArrayLong$$Type)) break; if (PySequence_Check(arg)) { if (PySequence_Length(arg) > 0) { PyObject *obj = PySequence_GetItem(arg, 0); int ok = PyLong_CheckExact(obj); Py_DECREF(obj); if (ok) break; } else break; } } else if (PyLong_CheckExact(arg)) break; return -1; } case 's': /* string */ { if (array) { if (arg == Py_None) break; if (PyObject_TypeCheck(arg, JArrayString$$Type)) break; if (PySequence_Check(arg) && !PyString_Check(arg) && !PyUnicode_Check(arg)) { if (PySequence_Length(arg) > 0) { PyObject *obj = PySequence_GetItem(arg, 0); int ok = (obj == Py_None || PyString_Check(obj) || PyUnicode_Check(obj)); Py_DECREF(obj); if (ok) break; } else break; } } else if (arg == Py_None || PyString_Check(arg) || PyUnicode_Check(arg)) break; return -1; } case 'o': /* java.lang.Object */ break; default: return -1; } if (types[pos] != '[') array = 0; } if (array) return -1; pos = 0; for (unsigned int a = 0; a < count; a++, pos++) { PyObject *arg = args[a]; switch (types[pos]) { case '[': { if (++array > 1) return -1; a -= 1; break; } case 'j': /* Java object except String and Object */ case 'k': /* Java object, with initializeClass */ case 'K': /* Java object, with initializeClass and params */ { jclass cls = NULL; switch (types[pos]) { case 'j': cls = (jclass) va_arg(check, Class *)->this$; break; case 'k': case 'K': getclassfn initializeClass = va_arg(check, getclassfn); cls = (*initializeClass)(); } if (array) { JArray *array = va_arg(list, JArray *); #ifdef _java_generics if (types[pos] == 'K') { PyTypeObject ***tp = va_arg(list, PyTypeObject ***); va_arg(list, getparametersfn); *tp = NULL; } #endif if (arg == Py_None) *array = JArray((jobject) NULL); else if (PyObject_TypeCheck(arg, JArrayObject$$Type)) *array = ((t_jarray *) arg)->array; else *array = JArray(cls, arg); if (PyErr_Occurred()) return -1; } else { Object *obj = va_arg(list, Object *); if (PyObject_TypeCheck(arg, &FinalizerProxy$$Type)) arg = ((t_fp *) arg)->object; #ifdef _java_generics if (types[pos] == 'K') { PyTypeObject ***tp = va_arg(list, PyTypeObject ***); PyTypeObject **(*parameters_)(void *) = va_arg(list, getparametersfn); if (arg == Py_None) *tp = NULL; else *tp = (*parameters_)(arg); } #endif *obj = arg == Py_None ? Object(NULL) : ((t_Object *) arg)->object; } break; } case 'Z': /* boolean, strict */ { if (array) { JArray *array = va_arg(list, JArray *); if (arg == Py_None) *array = JArray((jobject) NULL); else if (PyObject_TypeCheck(arg, JArrayBool$$Type)) *array = ((t_jarray *) arg)->array; else *array = JArray(arg); if (PyErr_Occurred()) return -1; } else { jboolean *b = va_arg(list, jboolean *); *b = arg == Py_True; } break; } case 'B': /* byte */ { if (array) { JArray *array = va_arg(list, JArray *); if (arg == Py_None) *array = JArray((jobject) NULL); else if (PyObject_TypeCheck(arg, JArrayByte$$Type)) *array = ((t_jarray *) arg)->array; else *array = JArray(arg); if (PyErr_Occurred()) return -1; } else if (PyString_Check(arg)) { jbyte *a = va_arg(list, jbyte *); *a = (jbyte) PyString_AS_STRING(arg)[0]; } else { jbyte *a = va_arg(list, jbyte *); *a = (jbyte) PyInt_AsLong(arg); } break; } case 'C': /* char */ { if (array) { JArray *array = va_arg(list, JArray *); if (arg == Py_None) *array = JArray((jobject) NULL); else if (PyObject_TypeCheck(arg, JArrayChar$$Type)) *array = ((t_jarray *) arg)->array; else *array = JArray(arg); if (PyErr_Occurred()) return -1; } else { jchar *c = va_arg(list, jchar *); *c = (jchar) PyUnicode_AS_UNICODE(arg)[0]; } break; } case 'I': /* int */ { if (array) { JArray *array = va_arg(list, JArray *); if (arg == Py_None) *array = JArray((jobject) NULL); else if (PyObject_TypeCheck(arg, JArrayInt$$Type)) *array = ((t_jarray *) arg)->array; else *array = JArray(arg); if (PyErr_Occurred()) return -1; } else { jint *n = va_arg(list, jint *); *n = (jint) PyInt_AsLong(arg); } break; } case 'S': /* short */ { if (array) { JArray *array = va_arg(list, JArray *); if (arg == Py_None) *array = JArray((jobject) NULL); else if (PyObject_TypeCheck(arg, JArrayShort$$Type)) *array = ((t_jarray *) arg)->array; else *array = JArray(arg); if (PyErr_Occurred()) return -1; } else { jshort *n = va_arg(list, jshort *); *n = (jshort) PyInt_AsLong(arg); } break; } case 'D': /* double */ { if (array) { JArray *array = va_arg(list, JArray *); if (arg == Py_None) *array = JArray((jobject) NULL); else if (PyObject_TypeCheck(arg, JArrayDouble$$Type)) *array = ((t_jarray *) arg)->array; else *array = JArray(arg); if (PyErr_Occurred()) return -1; } else { jdouble *d = va_arg(list, jdouble *); *d = (jdouble) PyFloat_AsDouble(arg); } break; } case 'F': /* float */ { if (array) { JArray *array = va_arg(list, JArray *); if (arg == Py_None) *array = JArray((jobject) NULL); else if (PyObject_TypeCheck(arg, JArrayFloat$$Type)) *array = ((t_jarray *) arg)->array; else *array = JArray(arg); if (PyErr_Occurred()) return -1; } else { jfloat *d = va_arg(list, jfloat *); *d = (jfloat) (float) PyFloat_AsDouble(arg); } break; } case 'J': /* long long */ { if (array) { JArray *array = va_arg(list, JArray *); if (arg == Py_None) *array = JArray((jobject) NULL); else if (PyObject_TypeCheck(arg, JArrayLong$$Type)) *array = ((t_jarray *) arg)->array; else *array = JArray(arg); if (PyErr_Occurred()) return -1; } else { jlong *l = va_arg(list, jlong *); *l = (jlong) PyLong_AsLongLong(arg); } break; } case 's': /* string */ { if (array) { JArray *array = va_arg(list, JArray *); if (arg == Py_None) *array = JArray((jobject) NULL); else if (PyObject_TypeCheck(arg, JArrayString$$Type)) *array = ((t_jarray *) arg)->array; else *array = JArray(arg); if (PyErr_Occurred()) return -1; } else { String *str = va_arg(list, String *); if (arg == Py_None) *str = String(NULL); else { *str = p2j(arg); if (PyErr_Occurred()) return -1; } } break; } case 'o': /* java.lang.Object */ { if (array) { JArray *array = va_arg(list, JArray *); if (arg == Py_None) *array = JArray((jobject) NULL); else *array = JArray(arg); if (PyErr_Occurred()) return -1; } else { Object *obj = va_arg(list, Object *); if (arg == Py_None) *obj = Object(NULL); else if (PyObject_TypeCheck(arg, &Object$$Type)) *obj = ((t_Object *) arg)->object; else if (PyObject_TypeCheck(arg, &FinalizerProxy$$Type)) { arg = ((t_fp *) arg)->object; if (PyObject_TypeCheck(arg, &Object$$Type)) *obj = ((t_Object *) arg)->object; else return -1; } else if (PyString_Check(arg) || PyUnicode_Check(arg)) { *obj = p2j(arg); if (PyErr_Occurred()) return -1; } else if (arg == Py_True) *obj = *Boolean::TRUE; else if (arg == Py_False) *obj = *Boolean::FALSE; else if (PyInt_Check(arg)) { long ln = PyInt_AS_LONG(arg); int n = (int) ln; if (ln != (long) n) *obj = Long((jlong) ln); else *obj = Integer((jint) n); } else if (PyLong_Check(arg)) *obj = Long((jlong) PyLong_AsLongLong(arg)); else if (PyFloat_Check(arg)) *obj = Double((jdouble) PyFloat_AS_DOUBLE(arg)); else return -1; } break; } default: return -1; } if (types[pos] != '[') array = 0; } if (pos == typeCount) return 0; return -1; } String p2j(PyObject *object) { return String(env->fromPyString(object)); } PyObject *j2p(const String& js) { return env->fromJString((jstring) js.this$, 0); } PyObject *PyErr_SetArgsError(char *name, PyObject *args) { if (!PyErr_Occurred()) { PyObject *err = Py_BuildValue("(sO)", name, args); PyErr_SetObject(PyExc_InvalidArgsError, err); Py_DECREF(err); } return NULL; } PyObject *PyErr_SetArgsError(PyObject *self, char *name, PyObject *args) { if (!PyErr_Occurred()) { PyObject *type = (PyObject *) self->ob_type; PyObject *err = Py_BuildValue("(OsO)", type, name, args); PyErr_SetObject(PyExc_InvalidArgsError, err); Py_DECREF(err); } return NULL; } PyObject *PyErr_SetArgsError(PyTypeObject *type, char *name, PyObject *args) { if (!PyErr_Occurred()) { PyObject *err = Py_BuildValue("(OsO)", type, name, args); PyErr_SetObject(PyExc_InvalidArgsError, err); Py_DECREF(err); } return NULL; } PyObject *PyErr_SetJavaError(jthrowable throwable) { PyObject *err = t_Throwable::wrap_Object(Throwable(throwable)); PyErr_SetObject(PyExc_JavaError, err); Py_DECREF(err); return NULL; } void throwPythonError(void) { PyObject *exc = PyErr_Occurred(); if (exc && PyErr_GivenExceptionMatches(exc, PyExc_JavaError)) { PyObject *value, *traceback; PyErr_Fetch(&exc, &value, &traceback); if (value) { PyObject *je = PyObject_CallMethod(value, "getJavaException", ""); if (!je) PyErr_Restore(exc, value, traceback); else { Py_DECREF(exc); Py_DECREF(value); Py_XDECREF(traceback); exc = je; if (exc && PyObject_TypeCheck(exc, &Throwable$$Type)) { jobject jobj = ((t_Throwable *) exc)->object.this$; env->get_vm_env()->Throw((jthrowable) jobj); Py_DECREF(exc); return; } } } else { Py_DECREF(exc); Py_XDECREF(traceback); } } else if (exc && PyErr_GivenExceptionMatches(exc, PyExc_StopIteration)) { PyErr_Clear(); return; } if (exc) { PyObject *name = PyObject_GetAttrString(exc, "__name__"); env->get_vm_env()->ThrowNew(env->getPythonExceptionClass(), PyString_AS_STRING(name)); Py_DECREF(name); } else env->get_vm_env()->ThrowNew(env->getPythonExceptionClass(), "python error"); } void throwTypeError(const char *name, PyObject *object) { PyObject *tuple = Py_BuildValue("(ssO)", "while calling", name, object); PyErr_SetObject(PyExc_TypeError, tuple); Py_DECREF(tuple); env->get_vm_env()->ThrowNew(env->getPythonExceptionClass(), "type error"); } int abstract_init(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *err = Py_BuildValue("(sO)", "instantiating java class", self->ob_type); PyErr_SetObject(PyExc_NotImplementedError, err); Py_DECREF(err); return -1; } PyObject *callSuper(PyTypeObject *type, const char *name, PyObject *args, int cardinality) { PyObject *super = (PyObject *) type->tp_base; PyObject *method = PyObject_GetAttrString(super, (char *) name); // python 2.4 cast PyObject *value; if (!method) return NULL; if (cardinality > 1) value = PyObject_Call(method, args, NULL); else { #if PY_VERSION_HEX < 0x02040000 PyObject *tuple = Py_BuildValue("(O)", args); #else PyObject *tuple = PyTuple_Pack(1, args); #endif value = PyObject_Call(method, tuple, NULL); Py_DECREF(tuple); } Py_DECREF(method); return value; } PyObject *callSuper(PyTypeObject *type, PyObject *self, const char *name, PyObject *args, int cardinality) { #if PY_VERSION_HEX < 0x02040000 PyObject *tuple = Py_BuildValue("(OO)", type, self); #else PyObject *tuple = PyTuple_Pack(2, type, self); #endif PyObject *super = PyObject_Call((PyObject *) &PySuper_Type, tuple, NULL); PyObject *method, *value; Py_DECREF(tuple); if (!super) return NULL; method = PyObject_GetAttrString(super, (char *) name); // python 2.4 cast Py_DECREF(super); if (!method) return NULL; if (cardinality > 1) value = PyObject_Call(method, args, NULL); else { #if PY_VERSION_HEX < 0x02040000 tuple = Py_BuildValue("(O)", args); #else tuple = PyTuple_Pack(1, args); #endif value = PyObject_Call(method, tuple, NULL); Py_DECREF(tuple); } Py_DECREF(method); return value; } PyObject *castCheck(PyObject *obj, getclassfn initializeClass, int reportError) { if (PyObject_TypeCheck(obj, &FinalizerProxy$$Type)) obj = ((t_fp *) obj)->object; if (!PyObject_TypeCheck(obj, &Object$$Type)) { if (reportError) PyErr_SetObject(PyExc_TypeError, obj); return NULL; } jobject jobj = ((t_Object *) obj)->object.this$; if (jobj) { jclass cls; try { cls = (*initializeClass)(); } catch (JCCEnv::pythonError e) { return NULL; } catch (JCCEnv::exception e) { PyErr_SetJavaError(e.throwable); return NULL; } if (!env->get_vm_env()->IsInstanceOf(jobj, cls)) { if (reportError) PyErr_SetObject(PyExc_TypeError, obj); return NULL; } } return obj; } PyObject *get_extension_iterator(PyObject *self) { return PyObject_CallMethod(self, "iterator", ""); } PyObject *get_extension_next(PyObject *self) { return PyObject_CallMethod(self, "next", ""); } PyObject *get_extension_nextElement(PyObject *self) { return PyObject_CallMethod(self, "nextElement", ""); } jobjectArray fromPySequence(jclass cls, PyObject *sequence) { if (sequence == Py_None) return NULL; if (!PySequence_Check(sequence)) { PyErr_SetObject(PyExc_TypeError, sequence); return NULL; } int length = PySequence_Length(sequence); jobjectArray array; try { array = env->newObjectArray(cls, length); } catch (JCCEnv::pythonError) { return NULL; } catch (JCCEnv::exception e) { PyErr_SetJavaError(e.throwable); return NULL; } JNIEnv *vm_env = env->get_vm_env(); for (int i = 0; i < length; i++) { PyObject *obj = PySequence_GetItem(sequence, i); int fromString = 0; jobject jobj; if (!obj) break; else if (obj == Py_None) jobj = NULL; else if (PyString_Check(obj) || PyUnicode_Check(obj)) { jobj = env->fromPyString(obj); fromString = 1; } else if (PyObject_TypeCheck(obj, &JObject$$Type)) jobj = ((t_JObject *) obj)->object.this$; else if (PyObject_TypeCheck(obj, &FinalizerProxy$$Type)) jobj = ((t_JObject *) ((t_fp *) obj)->object)->object.this$; else /* todo: add auto-boxing of primitive types */ { PyErr_SetObject(PyExc_TypeError, obj); Py_DECREF(obj); return NULL; } Py_DECREF(obj); try { env->setObjectArrayElement(array, i, jobj); if (fromString) vm_env->DeleteLocalRef(jobj); } catch (JCCEnv::exception e) { PyErr_SetJavaError(e.throwable); return NULL; } } return array; } void installType(PyTypeObject *type, PyObject *module, char *name, int isExtension) { if (PyType_Ready(type) == 0) { Py_INCREF(type); if (isExtension) { type->ob_type = &FinalizerClass$$Type; Py_INCREF(&FinalizerClass$$Type); } PyModule_AddObject(module, name, (PyObject *) type); } } PyObject *wrapType(PyTypeObject *type, const jobject& obj) { PyObject *cobj = PyObject_GetAttrString((PyObject *) type, "wrapfn_"); PyObject *(*wrapfn)(const jobject&); if (cobj == NULL) return NULL; wrapfn = (PyObject *(*)(const jobject &)) PyCObject_AsVoidPtr(cobj); Py_DECREF(cobj); return wrapfn(obj); } #ifdef _java_generics PyObject *typeParameters(PyTypeObject *types[], size_t size) { size_t count = size / sizeof(PyTypeObject *); PyObject *tuple = PyTuple_New(count); for (size_t i = 0; i < count; i++) { PyObject *type = (PyObject *) types[i]; if (type == NULL) type = Py_None; PyTuple_SET_ITEM(tuple, i, type); Py_INCREF(type); } return tuple; } #endif