Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Embed Java code into your native apps

Integrate a Java user interface with legacy code on Unix

  • Print
  • Feedback

Page 2 of 7

A Motif application using a Swing menu. The knight is drawn using OpenGL.

Allow Swing menu to call back legacy app

Now, what happens if you press the Swing buttons Red or Yellow in the figure above? Nothing yet. You would like the knight to change color, but for it to do so, you need to link your Java code to your legacy application. You must find a way to connect the legacy app with the Swing GUI. The java.awt.event package and JNI help complete that task. The AWT event model defines the ActionListener interface, which listens to the user interactions with the menu. That interface includes the actionPerformed() method, which is called when an action event occurs. The SwingMenu class must implement the ActionListener interface, and it must define the actionPerformed() method. In turn, actionPerformed() calls the changeColour() method that you have declared native in the SwingMenu class. Why native? Because changeColour() is actually implemented in C -- hence it can easily communicate with your legacy code. The C implementation is located in a dedicated dynamic library that you have named libNativeMethods.so, and that implementation finally calls your legacy function to change the knight's color.

Below is an example featuring a changeColour() method that ensures you can change the knight's color to red. The code below covers the declaration in the Java code, the actionPerformed() method implementation, and the prototyping in C:

Listing 2: Call a C function from Java

// File SwingMenu.java
// Implements the SwingMenu class
import javax.swing.*;
class SwingMenu extends JFrame implements ActionListener {
  JButton      redButton;
  // Declaring a method native
  private native void changeColour(int colour);
  static { system.loadLibrary("NativeMethods");  }
  // Method to create the Java GUI.
  public void initGUI(int mainWindow) {
     // Create the "Red" button.
     redButton = new JButton("Red");
     redButton.addActionListener(this);
  }
  // Method to handle button events.
  public void actionPerformed(ActionEvent e) {
      String string = e.getActionCommand();
      if (string.equals("Red")) { changeColour(1);  }
  }
}
/**  File nativeMethods.c **/
#include <jni.h>
#include <SwingMenu.h>
/*
 * Functions which is actually called when the changeColour() Java method
is called
 */
JNIEXPORT void JNICALL Java_SwingMenu_changeColour(JNIEnv env, jobject
obj, jint colour)
{
  legacyChangeColour((int)colour);   /* the legacyChangeColour() function
is defined in our legacy application */
  return;
}
jint JNI_Onload(JavaVM *vm, void *reserved)
{
   return (JNI_VERSION_1_2);
}


In Listing 2, the file nativeMethods.c implements the methods declared native. You can automatically generate the included file SwingMenu.h by using the javah tool on the SwingMenu class file. You should not modify that file; SwingMenu defines the prototypes of the C functions implementing the Java methods declared native. As you can see in Listing 2, the method name is slightly more complicated than changeColour().

Note that in the SwingMenu.java file, you must load the library libNativeMethods.so by calling System.loadLibrary(). Performing this call in a static block ensures that the library loads as soon as the Java class loads.

  • Print
  • Feedback

Resources