pyjnius/jnius/jnius_utils.pxi

205 lines
5.6 KiB
Cython
Raw Normal View History

2012-08-20 07:35:14 +00:00
cdef parse_definition(definition):
# not a function, just a field
if definition[0] != '(':
return definition, None
# it's a function!
argdef, ret = definition[1:].split(')')
args = []
while len(argdef):
c = argdef[0]
# read the array char
prefix = ''
if c == '[':
prefix = c
argdef = argdef[1:]
c = argdef[0]
# native type
if c in 'ZBCSIJFD':
args.append(prefix + c)
argdef = argdef[1:]
continue
# java class
if c == 'L':
c, argdef = argdef.split(';', 1)
args.append(prefix + c + ';')
return ret, args
cdef void check_exception(JNIEnv *j_env) except *:
cdef jthrowable exc = j_env[0].ExceptionOccurred(j_env)
if exc:
j_env[0].ExceptionDescribe(j_env)
j_env[0].ExceptionClear(j_env)
raise JavaException('JVM exception occured')
2012-08-20 07:40:18 +00:00
2012-08-20 08:34:14 +00:00
cdef dict assignable_from = {}
cdef void check_assignable_from(JNIEnv *env, JavaClass jc, bytes signature) except *:
cdef jclass cls
# if we have a JavaObject, it's always ok.
if signature == 'java/lang/Object':
return
# if the signature is a direct match, it's ok too :)
if jc.__javaclass__ == signature:
return
# if we already did the test before, use the cache result!
result = assignable_from.get((jc.__javaclass__, signature), None)
if result is None:
# we got an object that doesn't match with the signature
# check if we can use it.
cls = env[0].FindClass(env, signature)
if cls == NULL:
raise JavaException('Unable to found the class for {0!r}'.format(
signature))
result = bool(env[0].IsAssignableFrom(env, jc.j_cls, cls))
env[0].ExceptionClear(env)
print 'CHECK FOR', jc.__javaclass__, signature, result
assignable_from[(jc.__javaclass__, signature)] = bool(result)
if result is False:
raise JavaException('Invalid instance of {0!r} passed for a {1!r}'.format(
jc.__javaclass__, signature))
2012-08-20 07:35:14 +00:00
cdef bytes lookup_java_object_name(JNIEnv *j_env, jobject j_obj):
from reflect import ensureclass, autoclass
ensureclass('java.lang.Object')
ensureclass('java.lang.Class')
cdef JavaClass obj = autoclass('java.lang.Object')(noinstance=True)
obj.instanciate_from(create_local_ref(j_env, j_obj))
cls = obj.getClass()
name = cls.getName()
ensureclass(name)
return name.replace('.', '/')
2012-08-20 07:40:18 +00:00
cdef int calculate_score(sign_args, args) except *:
cdef int index
cdef int score = 0
cdef bytes r
cdef JavaClass jc
if len(args) != len(sign_args):
return -1
score += 10
for index in range(len(sign_args)):
r = sign_args[index]
arg = args[index]
if r == 'Z':
if not isinstance(arg, bool):
return -1
score += 10
continue
if r == 'B':
if not isinstance(arg, int):
return -1
score += 10
continue
if r == 'C':
if not isinstance(arg, str) or len(arg) != 1:
return -1
score += 10
continue
if r == 'S' or r == 'I' or r == 'J':
if isinstance(arg, int):
score += 10
continue
elif isinstance(arg, float):
score += 5
continue
else:
return -1
if r == 'F' or r == 'D':
if isinstance(arg, int):
score += 5
continue
elif isinstance(arg, float):
score += 10
continue
else:
return -1
if r[0] == 'L':
r = r[1:-1]
if arg is None:
score += 10
continue
# if it's a string, accept any python string
if r == 'java/lang/String' and isinstance(arg, basestring):
score += 10
continue
# if it's a generic object, accept python string, or any java
# class/object
if r == 'java/lang/Object':
if isinstance(arg, JavaClass) or isinstance(arg, JavaObject):
score += 10
continue
elif isinstance(arg, basestring):
score += 5
continue
return -1
# if we pass a JavaClass, ensure the definition is matching
# XXX FIXME what if we use a subclass or something ?
if isinstance(arg, JavaClass):
jc = arg
if jc.__javaclass__ == r:
score += 10
else:
2012-08-20 14:51:32 +00:00
#try:
# check_assignable_from(jc, r)
#except:
# return -1
score += 5
2012-08-20 07:40:18 +00:00
continue
# always accept unknow object, but can be dangerous too.
if isinstance(arg, JavaObject):
score += 1
continue
# native type? not accepted
return -1
if r[0] == '[':
if arg is None:
return 10
if not isinstance(arg, tuple) and not isinstance(arg, list):
return -1
# calculate the score for our subarray
subscore = calculate_score([r[1:]] * len(arg), arg)
if subscore == -1:
return -1
# look like the array is matching, accept it.
score += 10
continue
return score