Your Browser is not longer supported

Please use Google Chrome, Mozilla Firefox or Microsoft Edge to view the page correctly
Loading...

{{viewport.spaceProperty.prod}}

Implementation of a native method in C

Our sample application will consist of two Java classes Hello and Work, each of which contains a native method. One of them issues a greeting message, while the other performs a calculation. This example is highly artificial as normally no user would have this performed using native methods.

The native methods in both classes are to be stored in a common library called example1.

Implementation of the Java code

In a file called Hello.java the following Java class is defined:

class Hello { 
   public native void greetings(String text);
   static {
     System.loadLibrary("example1"); 
   }
   public static void main(String[] args) { 
       new Hello().greetings("Hello"); 
       new Work().compute(); 
   } 
} 

In the file Work.java the second Java class is defined:

import java.io.*;
class Work { 
   public native double docompute(double arg);
   public void compute() { 
     System.out.println("Resultat 1: " + docompute(1.0)); 
     System.out.println("Resultat 2: " + docompute(7.0)); 
     System.out.println("Resultat 3: " + docompute(3.11)); 
   }
} 

If you had wanted to store the native methods in different libraries, each class would have to load its own library during initialization.

Compiling the Java code

The two Java classes can now be simply compiled using the command

javac Hello.java

The dependent class Work is created during this compilation.

Creation of header files

The header files which are needed in order to implement the native methods can be generated from the class files using the tool javah:

javah -jni Hello
javah -jni Work

Once this step is complete, the header files Hello.h and Work.h will be available with the prototypes of the native functions.

Implementation of the C code

The native methods are now typically implemented in corresponding source files. In our example these will be the files Hello.c and Work.c. Both files include the header which is provided with JENV jni.h and in each case the associated header previously generated, Hello.h or Work.h. The function definition must match the prototype which has been generated. The further coding depends on the desired implementation.

The program Hello.c will now be implemented in the example as follows:

#include <jni.h> 
#include "Hello.h" 
#include <stdio.h> 
#include <stdlib.h>
#include <ascii_ebcdic.h>
JNIEXPORT void JNICALL 
Java_Hello_greetings(JNIEnv *env, jobject jthis, jstring text) 
{ 
  char *ebcdic_text; 
  const char *utf_text;
  utf_text = (*env)->GetStringUTFChars(env,text,NULL); 
  ebcdic_text = _a2e_dup(utf_text); 
  (*env)->ReleaseStringUTFChars(env,text,utf_text);
  printf("The program responds here %s\n",ebcdic_text); free(ebcdic_text); 
} 

The file Work.c contains the following code:

#include <jni.h> 
#include "Work.h" 
JNIEXPORT jdouble JNICALL 
Java_Work_docompute(JNIEnv *env, jobject jthis, jdouble num) 
{ 
  return (num < 1.7) ? num * 3.4 : num - 1.0; 
} 

In the file Work.c use has been made of the option of transparent usage of IEEE functions, described in more detail above. In file Hello.c explicit ASCII-EBCDI conversions are carried out.

To make the examples clear and at the same time keep them short, detailed error handling has been omitted.

Compiling the C source

The C source code implemented in the section above must now be compiled using the correct compiler options. For Hello.c these are the standard options which are described in more detail above:

cc -c -I/opt/java/include \
      -Kllm_keep,llm_case_lower \ 
      -Kworkspace_stack,c_names_unlimited Hello.c 

For Work.c the IEEE arithmetic must also be considered:

cc -c -I/opt/java/include \
      -Kllm_keep,llm_case_lower \ 
      -Kworkspace_stack,c_names_unlimited \
      -Kieee_floats Work.c 

This results in the object files being made available

Creation of the shared object

The previously created objects can be linked to a main module with the following command:

cc -r -B llm4 -o example1.o Hello.o Work.o

The main module created is then stored in a BS2000 library.

bs2cp example1.o bs2:'syslnk.example1(example1,L)'

Finally, a description file which complies with the naming convention is created. This must naturally contain the correct references.

mk_shobj -l syslnk.example1 -m example1 libexample1.so

Processing of the program

To run the program all that remains now is to set the environment variable LD_LIBRARY_PATH so that the created shared object is also found. In our example this can be done using

export LD_LIBRARY_PATH=.

The application can now be started with

java Hello