remove "holds"; more test cases; detect lambda in signature scoring

This commit is contained in:
Craig Macdonald 2020-04-21 21:04:56 +01:00
parent 30bbac7b1c
commit 2294c2d514
4 changed files with 37 additions and 12 deletions

View File

@ -29,14 +29,13 @@ cdef void release_args(JNIEnv *j_env, tuple definition_args, jvalue *j_args, arg
pass
j_env[0].DeleteLocalRef(j_env, j_args[index].l)
cdef list populate_args(JNIEnv *j_env, tuple definition_args, jvalue *j_args, args):
cdef void populate_args(JNIEnv *j_env, tuple definition_args, jvalue *j_args, args):
# do the conversion from a Python object to Java from a Java definition
cdef JavaClassStorage jcs
cdef JavaObject jo
cdef JavaClass jc
cdef PythonJavaClass pc
cdef int index
holds=[]
for index, argtype in enumerate(definition_args):
py_arg = args[index]
@ -108,13 +107,11 @@ cdef list populate_args(JNIEnv *j_env, tuple definition_args, jvalue *j_args, ar
j_args[index].l = convert_pyarray_to_java(j_env, argtype, py_arg)
# lambda or function
elif callable(py_arg) and argtype == "Ljava/util/function/Function;":
elif callable(py_arg):
# we need to make a java object in python
py_arg = convert_python_callable_to_jobject(argtype, py_arg)
# we need to keep that python object around
holds.append(py_arg)
# TODO: this line should not be needed to prevent py_arg from being GCd
activeLambdaJavaProxies.add(py_arg)
@ -154,7 +151,6 @@ cdef list populate_args(JNIEnv *j_env, tuple definition_args, jvalue *j_args, ar
'{0!r}'.format(py_arg))
j_args[index].l = convert_pyarray_to_java(
j_env, argtype[1:], py_arg)
return holds
cdef convert_jobject_to_python(JNIEnv *j_env, definition, jobject j_object):

View File

@ -850,14 +850,11 @@ cdef class JavaMethod(object):
try:
# convert python argument if necessary
# holds is a list of objects that need to be kept around for
# the lifetime of the call
holds = None
if len(args):
j_args = <jvalue *>malloc(sizeof(jvalue) * d_args_len)
if j_args == NULL:
raise MemoryError('Unable to allocate memory for java args')
holds = populate_args(j_env, self.definition_args, j_args, args)
populate_args(j_env, self.definition_args, j_args, args)
try:
# do the call

View File

@ -360,6 +360,11 @@ cdef int calculate_score(sign_args, args, is_varargs=False) except *:
score += 1
continue
# its a function or lambda, we can pass that as an object
if callable(arg):
score += 1
continue
# native type? not accepted
return -1

View File

@ -4,14 +4,34 @@ from jnius import autoclass, JavaException
class TestLambdas(unittest.TestCase):
def testCallable(self):
callFn = lambda: "done"
executor = autoclass("java.util.concurrent.Executors").newFixedThreadPool(1)
future = executor.submit(callFn)
print(type(future))
self.assertEqual("done", future.get())
executor.shutdownNow()
def testComparator(self):
numbers = autoclass('java.util.ArrayList')()
Collections = autoclass('java.util.Collections')
numbers.add(1)
numbers.add(3)
revSort = lambda i, j: j - i
Collections.sort(numbers, revSort)
self.assertEqual(numbers[0], 3)
self.assertEqual(numbers[1], 1)
def testJavaUtilFunction(self):
Arrays = autoclass("java.util.Arrays")
Collectors = autoclass("java.util.stream.Collectors")
#J: List<Integer> numbers = Arrays.asList(1, 2, 3);
numbers = autoclass('java.util.ArrayList')()
numbers.add(1)
numbers.add(2)
numbers.add(3)
def squareFn(i):
return i * i
#J: List<Integer> squares = numbers.stream().map( i -> i*i).collect(Collectors.toList());
squares = numbers.stream().map(lambda i : i * i).collect(Collectors.toList())
@ -20,6 +40,13 @@ class TestLambdas(unittest.TestCase):
self.assertEqual(squares[0], 1)
self.assertEqual(squares[1], 4)
self.assertEqual(squares[2], 9)
squares = numbers.stream().map(squareFn).collect(Collectors.toList())
self.assertEqual(len(squares), len(numbers))
self.assertEqual(squares[0], 1)
self.assertEqual(squares[1], 4)
self.assertEqual(squares[2], 9)
if __name__ == '__main__':