added convert_python_to_jobject: don't do convert to java primitive/jvalue, but jobject. fixed array translation.

This commit is contained in:
Mathieu Virbel 2013-01-02 18:11:12 +01:00
parent 143ab371b6
commit a2d0076e56
2 changed files with 113 additions and 54 deletions

View File

@ -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, <char *><bytes>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, '<init>', '(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, '<init>', '(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, '<init>', '(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, '<init>', '(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, '<init>', '(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, '<init>', '(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, '<init>', '(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, '<init>', '(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

View File

@ -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, '<init>', '(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, '<init>', '(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, '<init>', '(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, '<init>', '(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, '<init>', '(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, '<init>', '(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, '<init>', '(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, '<init>', '(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, ), <jvalue *>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)