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"