From a2d0076e561b8f7cad9689fcd58ecfc31d7e1aca Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Wed, 2 Jan 2013 18:11:12 +0100 Subject: [PATCH] added convert_python_to_jobject: don't do convert to java primitive/jvalue, but jobject. fixed array translation. --- jnius/jnius_conversion.pxi | 105 +++++++++++++++++++++++++++++++++++++ jnius/jnius_utils.pxi | 62 +++------------------- 2 files changed, 113 insertions(+), 54 deletions(-) diff --git a/jnius/jnius_conversion.pxi b/jnius/jnius_conversion.pxi index 46e6b42..e4b7ea2 100644 --- a/jnius/jnius_conversion.pxi +++ b/jnius/jnius_conversion.pxi @@ -253,6 +253,110 @@ cdef convert_jarray_to_python(JNIEnv *j_env, definition, jobject j_object): return ret +cdef jobject convert_python_to_jobject(JNIEnv *j_env, definition, obj) except *: + cdef jobject retobject, retsubobject + cdef jclass retclass + cdef jmethodID redmidinit + cdef jvalue j_ret[1] + cdef JavaClass jc + cdef JavaObject jo + cdef JavaClassStorage jcs + cdef PythonJavaClass pc + cdef int index + + print 'convert_python_to_jobject()', definition, repr(obj) + + if definition[0] == 'L': + if obj is None: + return NULL + elif isinstance(obj, basestring) and \ + definition in ('Ljava/lang/String;', 'Ljava/lang/Object;'): + return j_env[0].NewStringUTF(j_env, obj) + elif isinstance(obj, type): + jc = obj + return jc.j_cls + elif isinstance(obj, JavaClass): + jc = obj + check_assignable_from(j_env, jc, definition[1:-1]) + return jc.j_self.obj + elif isinstance(obj, JavaObject): + jo = obj + return jo.obj + elif isinstance(obj, MetaJavaClass): + jcs = obj.__cls_storage + return jcs.j_cls + elif isinstance(obj, PythonJavaClass): + # from python class, get the proxy/python class + pc = obj + # get the java class + jc = pc.j_self + # get the localref + return jc.j_self.obj + elif isinstance(obj, (tuple, list)): + return convert_pyarray_to_java(j_env, definition, obj) + else: + raise JavaException('Invalid python object for this ' + 'argument. Want {0!r}, got {1!r}'.format( + definition[1:-1], obj)) + + elif definition[0] == '[': + conversions = { + int: 'I', + bool: 'Z', + long: 'J', + float: 'F', + basestring: 'Ljava/lang/String;', + } + retclass = j_env[0].FindClass(j_env, 'java/lang/Object') + retobject = j_env[0].NewObjectArray(j_env, len(obj), retclass, NULL) + for index, item in enumerate(obj): + item_definition = conversions.get(type(item), definition[1:]) + retsubobject = convert_python_to_jobject( + j_env, item_definition, item) + j_env[0].SetObjectArrayElement(j_env, retobject, index, + retsubobject) + return retobject + + elif definition == 'B': + retclass = j_env[0].FindClass(j_env, 'java/lang/Byte') + retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(B)V') + j_ret[0].b = obj + elif definition == 'S': + retclass = j_env[0].FindClass(j_env, 'java/lang/Short') + retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(S)V') + j_ret[0].s = obj + elif definition == 'I': + retclass = j_env[0].FindClass(j_env, 'java/lang/Integer') + retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(I)V') + j_ret[0].i = obj + elif definition == 'J': + retclass = j_env[0].FindClass(j_env, 'java/lang/Long') + retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(J)V') + j_ret[0].j = obj + elif definition == 'F': + retclass = j_env[0].FindClass(j_env, 'java/lang/Float') + retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(F)V') + j_ret[0].f = obj + elif definition == 'D': + retclass = j_env[0].FindClass(j_env, 'java/lang/Double') + retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(D)V') + j_ret[0].d = obj + elif definition == 'C': + retclass = j_env[0].FindClass(j_env, 'java/lang/Char') + retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(C)V') + j_ret[0].c = ord(obj) + elif definition == 'Z': + retclass = j_env[0].FindClass(j_env, 'java/lang/Boolean') + retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(Z)V') + j_ret[0].z = 1 if obj else 0 + else: + assert(0) + + assert(retclass != NULL) + # XXX do we need a globalref or something ? + retobject = j_env[0].NewObjectA(j_env, retclass, retmidinit, j_ret) + return retobject + cdef jobject convert_pyarray_to_java(JNIEnv *j_env, definition, pyarray) except *: cdef jobject ret = NULL @@ -271,6 +375,7 @@ cdef jobject convert_pyarray_to_java(JNIEnv *j_env, definition, pyarray) except cdef JavaObject jo cdef JavaClass jc + if definition == 'Ljava/lang/Object;' and len(pyarray) > 0: # then the method will accept any array type as param # let's be as precise as we can diff --git a/jnius/jnius_utils.pxi b/jnius/jnius_utils.pxi index 6cd9a6d..73e6ae4 100644 --- a/jnius/jnius_utils.pxi +++ b/jnius/jnius_utils.pxi @@ -357,11 +357,7 @@ cdef jobject invoke0(JNIEnv *j_env, jobject j_this, jobject j_proxy, jobject # convert back to the return type # use the populate_args(), but in the reverse way :) - cdef jvalue j_ret[1] t = ret_signature[:1] - cdef jclass retclass = NULL - cdef jobject retobject - cdef jmethodID retmidinit # did python returned a "native" type ? jtype = None @@ -378,56 +374,13 @@ cdef jobject invoke0(JNIEnv *j_env, jobject j_this, jobject j_proxy, jobject elif len(ret_signature) == 1: jtype = ret_signature - # converting a native type to an Object for returning the value - if jtype is not None: - if jtype == 'B': - retclass = j_env[0].FindClass(j_env, 'java/lang/Byte') - retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(B)V') - j_ret[0].b = ret - elif jtype == 'S': - retclass = j_env[0].FindClass(j_env, 'java/lang/Short') - retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(S)V') - j_ret[0].s = ret - elif jtype == 'I': - retclass = j_env[0].FindClass(j_env, 'java/lang/Integer') - retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(I)V') - j_ret[0].i = ret - elif jtype == 'J': - retclass = j_env[0].FindClass(j_env, 'java/lang/Long') - retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(J)V') - j_ret[0].j = ret - elif jtype == 'F': - retclass = j_env[0].FindClass(j_env, 'java/lang/Float') - retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(F)V') - j_ret[0].f = ret - elif jtype == 'D': - retclass = j_env[0].FindClass(j_env, 'java/lang/Double') - retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(D)V') - j_ret[0].d = ret - elif jtype == 'C': - retclass = j_env[0].FindClass(j_env, 'java/lang/Char') - retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(C)V') - j_ret[0].c = ord(ret) - elif jtype == 'Z': - retclass = j_env[0].FindClass(j_env, 'java/lang/Boolean') - retmidinit = j_env[0].GetMethodID(j_env, retclass, '', '(Z)V') - j_ret[0].z = 1 if ret else 0 - else: - print 'jtype', jtype - assert(0) - - if retclass != NULL: - # XXX do we need a globalref or something ? - retobject = j_env[0].NewObjectA(j_env, retclass, retmidinit, j_ret) - return retobject - - # this is not a "native" type, so we should be able to convert it to object - # with populate_args(). - # (String, list/tuple, etc.) - populate_args(j_env, (ret_signature, ), j_ret, [ret]) - return j_ret[0].l - + cdef jobject jret + try: + jret = convert_python_to_jobject(j_env, jtype or ret_signature, ret) + return jret + except Exception as e: + traceback.print_exc(e) @@ -465,6 +418,7 @@ def test(): from .reflect import autoclass print '1: declare a TestImplem that implement Collection' + class TestImplemIterator(PythonJavaClass): __javainterfaces__ = ['java/util/Iterator'] @@ -522,7 +476,7 @@ def test(): return self.data print '2: instanciate the class, with some data' - a = TestImplem(1, 2, 3) + a = TestImplem(*range(10)) print a print dir(a)