Joachim 

would you be interested to write a little Chpater for the Pharo for the 
entreprise book?
I can help.

Ste

On 05 Apr 2014, at 14:32, 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
> 
> 


Reply via email to