Appendices: Extending jSMILE Library
From DSL
Why to Extend the Library
Sometimes it may be desirable to have a set of functionalities encapsulated inside a single method. These functionalities can be later executed on a batch basis by a single method call. A solution would be to derive a custom class from the jSMILE Network class.
There are situations, however, when an access to the "low level" SMILE interface would be desired. A performance concern could serve as a quite good an argument for that. In that case sources of jSMILE can be modified, and that is what is covered below.
The library is written using C++. It consists of no class but a set of functions, as required by Java Native Interface (JNI). The library contains a function getNetwork() which returns a reference to an original SMILE DSL_Network object. This object gives a full access to the network.
What is and What is Not Covered Below
In the following short tutorial we will assume a Java SDK version of 1.4.2. If you have a different version please beware that the procedure presented below might not apply without having made some adjustments. In that case refer to yours SDK documentation.
The following tutorial cannot be treated as a complete JNI (Java Native Interface) tutorial. We will concentrate on the process of tailoring the existing jSMILE library. We will not give an in-depth description on all the possible cases one might be willing to implement. For further help please refer to one of the JNI tutorials available on-line (see the links section below).
JNI allows the use of any of the native languages, e.g., C, C++, Fortran. In the following tutorial we will focus on C++ only. We will also concentrate only on Windows platform. To get help on JNI libraries under other platforms please refer to on-line resources.
We will not make a step-by-step tutorial. Some obvious shortcuts will be made. This tutorial is not meant to address the needs of novice users.
Adding a New Method
Step 1: Writing the Java Code
The first step is to create an interface that will be used to access native methods we will create later on in a native language. Let us take a look at the java_library\src\smile\Network.java file. It contains a number of prototypes of native methods, e.g.:
... public native void addArc(int parentHandle, int childHandle); public native void addArc(String parentId, String childId); ...
Suppose we want to add a method which would create a file with a network having only a root node. In the java_library\src\smile\Network.java file we will add this method's prototype as:
public native int createRootNetwork(String rootName, String fileName);
It will expect two parameters, the name of the root node (rootName) and the name of the file to write the network in (fileName).
Step 2: Compiling the Java Code
Once we have added the prototype of our method we have to recompile the code running the following command from java_library\src\ folder:
javac smile\Network.java
The reminder of this tutorial assumes that the output classes are put in java_library\bin\smile\ folder.
Step 3: Creating a JAR file
As the Java side of the library has changed we have to recreate the smile.jar file. To do that we run the following command from java_library\bin\ folder:
jar.exe cf smile.jar smile\*.*
This concludes the creation of a new JAR file. Application you are using have to include that file. If you wish to test the method we are implementing here using a sample application provided in jSMILE package, you have to put the smile.jar file in jsmile_tutorials\application\jar\ folder.
'Step 4: Creating the Header File
Now we have to generate the header file for the library. To do that we have to run the following command from java_library\bin\ folder:
javah -jni smile.Network
We have to be sure to have the path to javah.exe set in our PATH environment variable. This program is located in bin\ subfolder of the Java SDK folder. The reminder of this tutorial assumes that the generated file java_library\bin\jsmile_Network.h is put in c_library\src\ folder.
If we go to the file we will notice that the following record has been added:
/*
* Class: jsmile_Network
* Method: createRootNetwork
* Signature: (Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_jsmile_Network_createRootNetwork
(JNIEnv *, jobject, jstring, jstring);
Step 5: Writing the Native Method Implementation
The native method will be defined in c_library\src\jsmile_Network.cpp file. In our case it will look as follows:
/*
* Class: Network
* Method: createRootNetwork
* Signature: (Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_jsmile_Network_createRootNetwork
(JNIEnv *env, jobject obj, jstring rootName, jstring fileName) {
DSL_network* theNet = getNetwork(env,obj);
if (theNet==NULL) return DSL_OUT_OF_RANGE;
const char *sRootName = env->GetStringUTFChars(rootName, 0);
const char *sFileName = env->GetStringUTFChars(fileName, 0);
int res = theNet->AddNode(DSL_CPT, (char *)sRootName);
if (res != DSL_OUT_OF_RANGE)
res = theNet->WriteFile(sFileName, DSL_XDSL_FORMAT);
env->ReleaseStringUTFChars(rootName, sRootName);
env->ReleaseStringUTFChars(fileName, sFileName);
return res;
}
Note that apart from the code required by the JNI specification we are programming purely as if we were using only the C++ SMILE library. On that basis, someone who is proficient in C++ and have experience with SMILE and JNI can create a library to be used by someone knowing Java.
Step 6: Creating a Shared Library
c_library\ folder contains a Visual Studio 2003 (version 7.1) project to create the shared library. Before building it we have to perform the following two steps:
- Put the newest versions of SMILE libraries in c_library\smile\ folder (available on the SMILE Web site download page).
- Change two of the three include directories in the project properties: (1) %JAVA_HOME%\include\, and (2) %JAVA_HOME%\include\win32\.
The created library will be placed in c_library\output\ folder.
Step 7: Running the Application
Let us assume we want to test the freshly implemented native method on a sample Java application provided with jSMILE package. The following code would be added to the jsmile_tutorials\application\src\SmileApp\SmileApp.java file as a body of a separate method:
Network net = new Network();
net.createRootNetwork("root", "network.xdsl");
The only thing left is to compile our application ( jsmile_tutorials\application\src\SmileApp\SmileApp.java). We have to be sure that we add the jsmile.dll library folder to the PATH environment variable or put the library in one of the folders already present in this variable.
Useful Links
