Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Varargs support #26

Merged
merged 3 commits into from
Aug 31, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions jnius/jnius_conversion.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ cdef jobject convert_pyarray_to_java(JNIEnv *j_env, definition, pyarray) except
j_env[0].SetObjectArrayElement(
j_env, <jobjectArray>ret, i, NULL)
elif isinstance(arg, basestring) and \
definition == 'Ljava/lang/String;':
definition in ('Ljava/lang/String;', 'Ljava/lang/Object;'):
j_string = j_env[0].NewStringUTF(
j_env, <bytes>arg)
j_env[0].SetObjectArrayElement(
Expand All @@ -309,9 +309,9 @@ cdef jobject convert_pyarray_to_java(JNIEnv *j_env, definition, pyarray) except
j_env[0].SetObjectArrayElement(
j_env, <jobjectArray>ret, i, jo.obj)
else:
raise JavaException('Invalid variable used for L array')
raise JavaException('Invalid variable used for L array', definition, pyarray)

else:
raise JavaException('Invalid array definition')
raise JavaException('Invalid array definition', definition, pyarray)

return <jobject>ret
45 changes: 34 additions & 11 deletions jnius/jnius_export_class.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -123,40 +123,51 @@ cdef class JavaClass(object):
cdef jmethodID constructor = NULL

# get the constructor definition if exist
definitions = ['()V']
definitions = [('()V', False)]
if hasattr(self, '__javaconstructor__'):
definitions = self.__javaconstructor__
if isinstance(definitions, basestring):
definitions = [definitions]

if len(definitions) == 0:
raise JavaException('No constructor available')

elif len(definitions) == 1:
definition = definitions[0]
definition, is_varargs = definitions[0]
d_ret, d_args = parse_definition(definition)
if len(args) != len(d_args):

if is_varargs:
args_ = args[:len(d_args) - 1] + (args[len(d_args) - 1:],)
else:
args_ = args
if len(args or ()) != len(d_args or ()):
raise JavaException('Invalid call, number of argument'
' mismatch for constructor')
else:
scores = []
for definition in definitions:
for definition, is_varargs in definitions:
d_ret, d_args = parse_definition(definition)
if is_varargs:
args_ = args[:len(d_args) - 1] + (args[len(d_args) - 1:],)
else:
args_ = args

score = calculate_score(d_args, args)
if score == -1:
continue
scores.append((score, definition, d_ret, d_args))
scores.append((score, definition, d_ret, d_args, args_))
if not scores:
raise JavaException('No constructor matching your arguments')
scores.sort()
score, definition, d_ret, d_args = scores[-1]
score, definition, d_ret, d_args, args_ = scores[-1]

try:
# convert python arguments to java arguments
if len(args):
j_args = <jvalue *>malloc(sizeof(jvalue) * len(d_args))
if j_args == NULL:
raise MemoryError('Unable to allocate memory for java args')
populate_args(self.j_env, d_args, j_args, args)
populate_args(self.j_env, d_args, j_args, args_)

# get the java constructor
constructor = self.j_env[0].GetMethodID(
Expand Down Expand Up @@ -417,6 +428,7 @@ cdef class JavaMethod(object):
cdef bytes classname
cdef bytes definition
cdef object is_static
cdef bint is_varargs
cdef object definition_return
cdef object definition_args

Expand All @@ -432,6 +444,7 @@ cdef class JavaMethod(object):
self.definition_return, self.definition_args = \
parse_definition(definition)
self.is_static = kwargs.get('static', False)
self.is_varargs = kwargs.get('varargs', False)

cdef void ensure_method(self) except *:
if self.j_method != NULL:
Expand Down Expand Up @@ -470,6 +483,9 @@ cdef class JavaMethod(object):
# argument array to pass to the method
cdef jvalue *j_args = NULL
cdef list d_args = self.definition_args
if self.is_varargs:
args = args[:len(d_args) - 1] + (args[len(d_args) - 1:],)

if len(args) != len(d_args):
raise JavaException('Invalid call, number of argument mismatch')

Expand Down Expand Up @@ -685,19 +701,19 @@ cdef class JavaMultipleMethod(object):
self.name = name
self.classname = classname

for signature, static in self.definitions:
for signature, static, is_varargs in self.definitions:
jm = None
if j_self is None and static:
if signature in self.static_methods:
continue
jm = JavaStaticMethod(signature)
jm = JavaStaticMethod(signature, varargs=is_varargs)
jm.set_resolve_info(j_env, j_cls, j_self, name, classname)
self.static_methods[signature] = jm

elif j_self is not None and not static:
if signature in self.instance_methods:
continue
jm = JavaMethod(signature)
jm = JavaMethod(signature, varargs=is_varargs)
jm.set_resolve_info(j_env, j_cls, None, name, classname)
self.instance_methods[signature] = jm

Expand All @@ -714,7 +730,14 @@ cdef class JavaMultipleMethod(object):

for signature in methods:
sign_ret, sign_args = parse_definition(signature)
score = calculate_score(sign_args, args)
jm = methods[signature]
if jm.is_varargs:
args_ = args[:len(sign_args) - 1] + (args[len(sign_args) - 1:],)
else:
args_ = args

score = calculate_score(sign_args, args_)

if score <= 0:
continue
scores.append((score, signature))
Expand Down
12 changes: 8 additions & 4 deletions jnius/reflect.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class Method(JavaClass):
getParameterTypes = JavaMethod('()[Ljava/lang/Class;')
getReturnType = JavaMethod('()Ljava/lang/Class;')
getModifiers = JavaMethod('()I')
isVarArgs = JavaMethod('()Z')


class Field(JavaClass):
Expand All @@ -65,6 +66,7 @@ class Constructor(JavaClass):
toString = JavaMethod('()Ljava/lang/String;')
getParameterTypes = JavaMethod('()[Ljava/lang/Class;')
getModifiers = JavaMethod('()I')
isVarArgs = JavaMethod('()Z')

def get_signature(cls_tp):
tp = cls_tp.getName()
Expand Down Expand Up @@ -98,7 +100,8 @@ def ensureclass(clsname):
def autoclass(clsname):
jniname = clsname.replace('.', '/')
cls = MetaJavaClass.get_javaclass(jniname)
if cls: return cls
if cls:
return cls

classDict = {}

Expand All @@ -112,7 +115,7 @@ def autoclass(clsname):
for constructor in c.getConstructors():
sig = '({0})V'.format(
''.join([get_signature(x) for x in constructor.getParameterTypes()]))
constructors.append(sig)
constructors.append((sig, constructor.isVarArgs()))
classDict['__javaconstructor__'] = constructors

methods = c.getMethods()
Expand All @@ -126,11 +129,12 @@ def autoclass(clsname):
# only one method available
if count == 1:
static = Modifier.isStatic(method.getModifiers())
varargs = method.isVarArgs()
sig = '({0}){1}'.format(
''.join([get_signature(x) for x in method.getParameterTypes()]),
get_signature(method.getReturnType()))
cls = JavaStaticMethod if static else JavaMethod
classDict[name] = cls(sig)
classDict[name] = cls(sig, varargs=varargs)
continue

# multpile signatures
Expand Down Expand Up @@ -158,7 +162,7 @@ def autoclass(clsname):
print 'Abstract', Modifier.isAbstract(m)
print 'Strict', Modifier.isStrict(m)
'''
signatures.append((sig, Modifier.isStatic(method.getModifiers())))
signatures.append((sig, Modifier.isStatic(method.getModifiers()), method.isVarArgs()))

classDict[name] = JavaMultipleMethod(signatures)

Expand Down
6 changes: 6 additions & 0 deletions tests/test_implementation.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import unittest
from jnius.reflect import autoclass


class ImplementationTest(unittest.TestCase):

def test_println(self):
# System.out.println implies recursive lookup, and j_self assignation.
# It was crashing during the implementation :/
System = autoclass('java.lang.System')
System.out.println('')

def test_printf(self):
System = autoclass('java.lang.System')
System.out.printf('hi\n')
System.out.printf('hi %s %s\n', 'jnius', 'other string')