Hi Joachim,

Thanks for the explanations. It looks complicated but I am very happy it is
possible!

I will give a try next week and get back to you.

Cheers,
Doru


On Sat, Apr 5, 2014 at 2:32 PM, Joachim Geidel <joachim.gei...@onlinehome.de
> wrote:

> Am 31.03.2014 um 21:25 schrieb Tudor Girba <tu...@tudorgirba.com>:
> > Now, the next question. I saw that it is possible to enable callbacks,
> but I could not find an example of how it works.
> >
> > For example, could we model this:
> >
> > - in a JavaClassOriginator class we have a method like
> > execute(JavaClassTargetInterface target) { target.m() }
> > - In Pharo we create PharoClassTargetImplementation as an implementation
> of JavaClassTargetInterface
> > - passing an instance of PharoClassTargetImplementation to
> JavaClassOriginator results in calling PharoClassTargetImplementation>>m
> >
> > ?
> >
> >
> > Cheers,
> > Doru
>
> Hi Doru,
>
> it's not completely straightforward, but also not really complicated.
> Chris Uppal's JNIPort documentation contains examples, and you can also get
> some information from the test cases for callbacks. You will need the
> jniport.jar file which can be downloaded from
> http://jniport.wikispaces.com/Downloads (it is contained in
> JNIPort_Extras.zip). The Java classes needed for callback support have
> names starting with "Dolphin" - they come directly from Chris'
> implementation for Dolphin Smalltalk.
>
> A simple example: To set up sending a simple notification without
> parameters to a Smalltalk object, you need a Java class similar to the
> following:
>
> -----------------
> package my.package;
> import org.metagnostic.jniport.*;
> public class MyClass
> {
>         private static final Object     notifyTag = new
> String("MyClass.sendNotification()");
>         public static Object notifyTag () { return notifyTag; }
>         public void sendNotification()
>                 throws RequestNotHandedException
>                 {
>                         new DolphinNotification(notifyTag, this).send();
>                 }
> }
> -----------------
>
> You have to install the callback in Smalltalk:
>
> -----------------
> NotificationHandler := ... "the object which receives the notifications"
> classStatic := jvm findClass: 'my.package.MyClass'.
> jvm callbackRegistry
>         setCallback: classStatic notifyTag "the tag can be an arbitrary
> String"
>         handler: [:this :param | NotificationHandler
> handleNotificationFor: this].
> -----------------
>
> When you send sendNotification() to an instance of MyClass,
> NotificationHandler should receive the message #handleNotificationFor:.
>
> In the example code, the tag is a static variable in MyClass. Of course,
> you can also give every instance of MyClass its own tag. In this case, you
> have to set up a callback in Smalltalk for every tag which is used.
>
> The example is a short version of the test code for handling notifications
> in JNIPortCallbackNotificationsTest and the corresponding Java class
> org.metagnostic.jniport.test.regression.Notifications. The source code of
> this Java class is in the archive JNIPort-Tests.zip which is contained in
> JNIPort_Extras.zip.
>
> If you need an example for a notification which has parameters and where
> the Smalltalk code returns  a result, have a look at
> JNIPortCallbackRequestsTest>>testCallbackWithOneParameterAndReturn and the
> corresponding Java class org.metagnostic.jniport.test.regression.Callbacks.
>
> In the Java class, you need something like this (copied from Callbacks and
> simplified) which enables a callback taking an int parameter and returning
> an instance of the Java class Integer:
>
>          private static final Object callbackTag = new String("callback
> with parameters"),
>
>         // callback with return value
>         public int callbackAndReturn(int i)
>         throws Throwable
>         {
>                 Object returnValue = new DolphinRequest(callbackTag, this,
> i).value();
>                 return ((Integer) returnValue).intValue();
>         }
>
> A DolphinRequest is created with the tag which identifies the callback in
> Smalltalk, the object sending the callback (this), and an arbitrary number
> of parameters. For example, the following creates a DolphinRequest with two
> parameters:
>
>                 DolphinRequest dr = new DolphinRequest(
>                                         s_callbackTag,
>                                         this,
>                                         new Integer(i),
>                                         new Double(d));
>
> Calling the value() method of the DolphinRequest sends the request to
> VisualWorks and returns the result of the Smalltalk callback block.
>
> In Smalltalk, you can create callbacks accepting parameters like this (see
> JNIPortCallbackRequestsTest):
>
>         "No parameters"
>         jvm callbackRegistry setCallback: classStatic callbackTag
>                         handler: [:this :param | self handleCallbackFor:
> this].
>
>         "One parameter"
>         jvm callbackRegistry setCallback: classStatic callbackTag
>                         handler: [:this :param | self handleCallbackFor:
> this with: param].
>
>         "Arbitrary number of parameters"
>         jvm callbackRegistry setCallback: classStatic callbackTag
>                         handler: [:this :params | self handleCallbackFor:
> this withArguments: params asArray].
>
> If the callback has a result which should be passed from Smalltalk to
> Java, it must be a Java object. Here is an example from the test class
> (callbacksStatus is just an instance variable of
> JNIPortCallbackRequestsTest):
>
> handleCallbackFor: aJavaObject with: anotherJavaObject
>
>         | jliClass |
>
>         jliClass := jvm findClass: #'java.lang.Integer'.
>
>         callbacksStatus addLast: (aJavaObject = instance).      "identity
> test on the Java object"
>         callbacksStatus addLast: ((anotherJavaObject static = jliClass)
> and: [anotherJavaObject intValue = 1]).
>
>         ^ jliClass new_int: 15. "Do not return a Smalltalk Integer. It
> must be a Java Integer"
>
> Johan Brichau's JavaConnect had a more direct way of creating callbacks,
> using Java's dynamic proxies. However, it had an open issue, as it relied
> on different Java objects having different identity hashes, which is not
> true in all cases. JNIPort's implementation is relatively complicated
> because it had to take into account that the callbacks can be triggered
> from a different thread than the Smalltalk thread. In VisualWorks, that's
> not a problem, as the VM handles this, and Pharo simply does not support
> callbacks from foreign threads. So, it could be simplified in JNIPort as
> well.
>
> Does this help?
> Joachim
>
>
>


-- 
www.tudorgirba.com

"Every thing has its own flow"

Reply via email to