Gem #55: Introduction to Ada / Java Interfacing

by Quentin Ochem —AdaCore

Let's get started…


Suppose we have an API (Application Program Interface) on the Ada side that we would like to call from Java. This API may be based on a set of types and functions, for example:

package API is

   type R is record
      F1, F2 : Integer;
   end record;

   procedure Print (Str : String; V : R);

end API;

Our purpose is to create an object of type R from Java, and then pass that object to the Ada Print procedure, along with a string parameter.


Generating the binding code

Now we need to generate the Java code as well as the extra JNI layer that will connect to the Ada code. This can be done using the ada2java tool, called as follows:

ada2java api.ads –b test –o ada –c java –L my_lib

Since the tool only generates the binding to the package, it only needs access to the specification (the api.ads file).

Then, for organizational purposes, we provide the name of the base package for all the generated Java classes, using the –b flag. Here, all the generated classes and packages will be children of the Java package “test”.

The –o and –c flags define the directory where, respectively, the Ada and the Java generated code will be stored. Here, we put the Ada code in the directory ada/ and the java code in the directory java/.

Finally, the main Ada code (here, the package My_Package) and the generated glue code needs to be compiled in a shared library that will be loaded by Java. In order to simplify the process, it is possible to generate a GNAT project file for input to gprbuild that will handle compilation of this library, by using the –L switch.


Writing the Java code

If you take a look at the content of the java/ directory, you willl find a bunch of classes, in particular:

test.API.R
test.API.API_Package
test.Standard.AdaString

These are all the classes needed by our application. test.API.R maps to the Ada R object, test.API.API_Package contains all the subprogram declarations that come from the API package and cannot be defined as members of other types, and test.Standard.AdaString is an automatically generated class that maps the standard String type.

Observe that the test.API.R class comes with accessors and modifiers for the F1 and F2 fields, and includes a default constructor. Note also that test.Standard.AdaString comes with a constructor based on java.lang.String.


It is now time to write the main Java class:

import test.API.R;
import test.API.API_Package;
import test.Standard.AdaString;

public class My_Main {

public static void main (String [] argv) {
   R v = new R ();
   v.F1 (10);
   v.F2 (15);
  API_Package.Print (new AdaString (“Hello”), v);
}

}

That’s it – this works just as if you had written a call directly from Java to Ada!


Compiling and running the code

The last step is to compile and run the code. Since we’ve already created the GNAT project file for the Ada code, compiling it only requires running gprbuild on it:

gprbuild –p –P ada/my_lib.gpr

Now you need to adapt either the PATH (on Windows) or LD_LIBRARY_PATH (on Linux/Solaris) in order to list the ada/lib directory, for example:

LD_LIBRARY_PATH=`pwd`/ada/lib/:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH

The generated java code must be in your CLASSPATH, as well as the main subprogram that you’ve written, and the lib/ajis.jar file of your AJIS installation. Let’s assume that you’re running on Linux, and your Java main is at the same location as the api.ads file. You’ll need:

CLASSPATH=`pwd`:`pwd`/java:<your AJIS installation>/lib/ajis.jar:$CLASSPATH

Compiling and running the Java code is now straightforward:

javac My_Main.java
java My_Main

Note that the library that we’ve compiled will be automatically loaded by the generated bound code.

Upcoming Gems will show more advanced usage of GNAT-AJIS, including using callbacks, OOP, exceptions, and memory management.


About the Author

Quentin Ochem has a software engineering background, specialized in software development for critical applications. He has over 10 years of experience in Ada development. He works today as a technical account manager for AdaCore, following projects related to avionics, railroad, space and defense industries. He also teaches the avionics standard DO-178B course at the EPITA University in Paris.