Message6641

Author dtmGoogle
Recipients dtmGoogle
Date 2011-09-07.14:02:07
SpamBayes Score 1.6653345e-16
Marked as misclassified No
Message-id <1315404128.71.0.62079274999.issue1795@psf.upfronthosting.co.za>
In-reply-to
Content
First, note that threading.py contains these two classes:

class JavaThread(object):
class Thread(JavaThread):

That is, "JavaThread" extends only python objects (although it contains a native java thread). Therefore, it should be possible to extend both Thread and a java interface, and then pass an instance of the resulting class to a java function accepting the interface.  However, if you try something like that after defining a single-method interface and a function that accepts an instance of that interface:

# BEGIN
from com.invitemedia.jython import JythonTestMethods
from com.invitemedia.jython import StringInterface
from threading import Thread

class Foo(Thread, StringInterface):
  def stringMethod(self):
    return "yo yo yo"

a = JythonTestMethods()

print a.doStringInterfaceThing(Foo())
# END

You end up with this error:

$ CLASSPATH=bin /opt/jython*/bin/jython ~/testThreadtojava.py 
Traceback (most recent call last):
  File "/home/dtm/testThreadtojava.py", line 11, in <module>
    print a.doStringInterfaceThing(Foo())
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:616)

java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: argument type mismatch

The issue is a combination of how threading.JavaThread overrides __tojava__ and how PyObjectDerived implements __tojava__.

JavaThread says:
    def __tojava__(self, c):
        if isinstance(self._thread, c):
            return self._thread
        if isinstance(self, c):
            return self
        return Py.NoConversion

PyObjectDerived says (in part, but this is the relevant part):
        PyType self_type=getType();
        PyObject impl=self_type.lookup("__tojava__");
        if (impl!=null)
            return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class);
        return super.__tojava__(c);

What happens is that JavaThread's __tojava__ method is first called with StringInterface; this hits the "return self" line, which then results in JavaThread's __tojava__ method being called with Java.lang.Object and hitting the "return self._thread" line. The end result is that PyObjectDerived's __tojava__ called with StringInterface.class returns an org.python.core.FunctionThread object.

I think that the best solution to this is to modify PyObjectDerived so that if  __call__ to the __tojava__ method returns *this*, we delegate to super.__tojava__(c). Patch attached.

With the patch applied, the script above works as it should.
History
Date User Action Args
2011-09-07 14:02:08dtmGooglesetrecipients: + dtmGoogle
2011-09-07 14:02:08dtmGooglesetmessageid: <1315404128.71.0.62079274999.issue1795@psf.upfronthosting.co.za>
2011-09-07 14:02:08dtmGooglelinkissue1795 messages
2011-09-07 14:02:08dtmGooglecreate