How can I inject a Java object into the interpreter?

64 views
Skip to first unread message

Sandeep Kumar

unread,
Dec 19, 2014, 11:28:15 AM12/19/14
to jtcl-p...@googlegroups.com
I have managed to write an Android program that embeds the jtcl interpreter, but I want to be able to inject my Android context (android.content.Context) into the interpreter so that scripts can invoke methods on it. Something like
interp.setVar("context", tclobj)

I don't fully understand how to convert an existing Java object into a TclObject.

Thanks,
--sandeep

Tom Poindexter

unread,
Dec 19, 2014, 3:18:43 PM12/19/14
to jtcl-p...@googlegroups.com
You need to wrap up your Java object into a ReflectObject (which is a type of TclObject), something like:

interp.setVar("context", tcl.pkg.java.ReflectObject.newInstance(interp, android.content.Context.class, content), flags);

where flags is one of: TCL.GLOBAL_ONLY, TCL.NAMESPACE_ONLY, or (int) 0
and content is your Java object.


Be sure to let us know about your Android app!

-Tom

Sandeep Kumar

unread,
Dec 20, 2014, 1:50:47 AM12/20/14
to jtcl-p...@googlegroups.com
Thanks Tom. That worked well. Now I'm stuck with another issue. How can I subclass in jtcl an abstract class in Java and provide an implementation for an abstract method in jtcl? I'm trying to write a BroadcastReceiver to get the battery level in Android in jtcl, and started along the following lines:

-------------------------------------------------------------------------------------------------------
set batteryLevelReceiver [java::new android.content.BroadcastReceiver]
java::bind $batteryLevelReceiver onReceive {
  set ctx [java::event -index 0]
  set intent [java::event -index 1]
  $ctx unregisterReceiver $batteryLevelReceiver
  set currentLevel [$intent getIntExtra "level" -1]
  set scale [$intent getIntExtra "scale" -1]
  set level -1
  if {currentLevel >= 0 && scale > 0} {
    set level [expr (currentLevel * 100) / scale]
  }
 
  append it "Battery Level Remaining: $level%"
}

set batteryLevelFilter [java::new android.content.IntentFilter "android.intent.action.BATTERY_CHANGED"]
$context registerReceiver batteryLevelReceiver batteryLevelFilter
-------------------------------------------------------------------------------------------------------

First off, I couldn't create an instance of an abstract class, so the first line failed. Fair enough, then I created a DummyBroadcastReceiver derived from BroadcastReceiver that had an empty onReceive method. But that didn't work either. I imagine that this would work if onReceive was an interface method that BroadcastReceiver was implementing, but that's beyond my control. Can you suggest a possible workaround to some other artifice?

Thanks,
--sandeep

Tom Poindexter

unread,
Dec 21, 2014, 3:19:43 PM12/21/14
to Sandeep Kumar, jtcl-p...@googlegroups.com
Right, just like Java, you'll need a concrete class to work with.

I've not had much experience using the java::bind command, I'm not sure all of the events that java::bind can handle.

In my Aejaks project, I deal with Java object events from a windowing system and provide callbacks in Tcl (much the way java::bind works).    The strategy is:

1. write a Java class that provides a listener for the windowing event class  (eg. your DummyBroadcasReceiver)
2. write a TclEvent subclass that evals the Tcl code
3. for the event method implementation, create one of your TclEvent objects and put it on the Tcl interp event queue.
4. JTcl will process the event.

Note that you shouldn't try to eval Tcl code in your event handler directly, which can cause problems.  You you always create a TclEvent and put the TclEvent on the interpreters event queue (the JTcl eval methods are not thread safe).  Using TclEvent will ensure that only one Tcl callback is accessing the Interp.


My Aejaks project is at: http://sourceforge.net/projects/aejaks/
The java code in src/java/org/aejaks/app/  has the event handler classes. 

Also, Swank (another windowing system for JTcl) deals with events with Tcl callbacks: https://swank.kenai.com/

Lastly, the 'java::bind' command can also be used as a reference, see:
and the other support classes it uses.

-Tom

--
You received this message because you are subscribed to the Google Groups "jtcl-project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jtcl-project...@googlegroups.com.
To post to this group, send email to jtcl-p...@googlegroups.com.
Visit this group at http://groups.google.com/group/jtcl-project.
To view this discussion on the web visit https://groups.google.com/d/msgid/jtcl-project/580d5cf1-3b2a-4317-98cd-692a0f6bf9dd%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages