[Spice_discussion] Calling SPICE from Java
Turner, Scott
Scott.Turner at jhuapl.edu
Tue Sep 19 09:06:03 PDT 2006
The approach I have used in the past with success was to utilize the
Java native interface (JNI). Sun provides some detailed and useful
documentation on the whole JNI process here:
http://java.sun.com/j2se/1.5.0/docs/guide/jni/
The basic idea is: you write wrappers in C for the SPICE functions from
CSPICE you want available in your Java applications. (furnsh_c,
spkezr_c, etc.) These wrappers really just translate inputs and outputs
between the two languages and ultimately invoke the native C method from
CSPICE. Then you compile these wrappers along with CSPICE into a shared
library (or dynamic link library in Windows-speak). Next you write a
class (or classes, but I found it convenient to simply lump everything
into a single "Spice" class) which declares the native methods you've
wrapped like this:
public static native void furnsh ( String file ) throws
SpiceException;
The SpiceException is a class I created to capture any SPICE errors that
result from invoking the wrappers. This is necessary because the
default error handler in CSPICE executes a call to exit() directly,
which will abruptly terminate the running JVM. To work around this, I
just created a simple initialization method that places the error
handler into return mode. Then in my CSPICE wrappers I translate
inputs, invoke the native CSPICE method, check for any SPICE errors,
then translate outputs. If a SPICE error occurs, I invoke another
special native method I wrote that generates a SpiceException and clears
the error handler so subsequent calls will function properly. (This is
a bit dangerous, if the error is sufficiently fatal you may have to
restart your application and reload the native library to recover.)
The "Spice" Java class to which I was alluding looks something like
this: (At the time, I was only interested in some elements of the time
conversion API.)
package spice;
public class Spice
{
public static native void jiniterr();
public static native void furnsh ( String file )
throws SpiceException;
public static native double str2et ( String timestring )
throws SpiceException;
public static native String timout ( double et, String picture )
throws SpiceException;
public static native void unload ( String file )
throws SpiceException;
static
{
/*
* Load the JNI interface to CSPICE.
*/
System.loadLibrary( "jnispice" );
/*
* Configure the SPICE error handler.
*/
jiniterr();
}
}
The static block is executed when the class is loaded. The
System.loadLibrary() routine will seek out libraries named
libjnicspice.so on Unix systems, or jnicspice.dll under Windows (I
think). You can append paths to the native library search mechanism
when you launch the JVM by defining the property "java.library.path".
Note: when you link native code into your Java applications you do lose
the "write once, run anywhere" aspect of the language. You will need to
compile and distribute libraries for each of environments you're
targeting for deployment of your Java code.
In my native method definitions, I opted to return values directly. For
example, str2et_c's prototype is:
void str2et_c( ConstSpiceChar *date, SpiceDouble *et )
But, observe my wrapper returns a double:
public static native double str2et ( String timestring )
throws SpiceException;
I did it this way only because it seemed convenient and more natural at
the time. I could have just as easily defined str2et this way:
public static native void str2et ( String timestring, double[] et )
throws SpiceException;
and then passed an array of type double[] with a single element into the
wrapper routine. Looking at this from a Java mentality though, it
seemed a rather clunky approach. However, you will need to do something
like this if you wrap spkezr_c and wish to preserve both the state and
light time output arguments for instance. Another approach is to make
"return value" classes, and populate instances of them in the native
wrappers. This might be a better option, but I didn't research it
sufficiently.
Hope this helps. If you have any questions, or would like to look at my
native wrapper or Java source as a starting point, just let me know.
I'd be happy to send the code along.
Scott
Scott Turner
Science Applications Group
Johns Hopkins University Applied Physics Laboratory
Scott.Turner at jhuapl.edu
-----Original Message-----
From: spice_discussion-bounces at naif.jpl.nasa.gov
[mailto:spice_discussion-bounces at naif.jpl.nasa.gov] On Behalf Of William
Thompson
Sent: Tuesday, September 19, 2006 9:17 AM
To: spice_discussion at naif.jpl.nasa.gov
Cc: EXT Goetz, Keith
Subject: [Spice_discussion] Calling SPICE from Java
A colleague of mine wants to access SPICE ephemerides from within a Java
application. Has anybody done this before? Any hints about how to go
about it?
If you could, please respond directly to my colleague at
"goetz at waves.space.umn.edu".
Thank you,
--
William Thompson
NASA Goddard Space Flight Center
Code 612.1
Greenbelt, MD 20771
USA
301-286-2040
William.T.Thompson.1 at gsfc.nasa.gov
_______________________________________________
Spice_discussion mailing list
Spice_discussion at naif.jpl.nasa.gov
http://naif.jpl.nasa.gov/mailman/listinfo/spice_discussion
More information about the Spice_discussion
mailing list