Book: JNI technology BASICS (1) -- writing JNI code from scratch
2. Compile the source program helloworld. Java and generate helloworld. Class.
3. Generate the header file helloworld. h
On the Linux console, enter the command javah-JNI helloworld to generate the helloworld. h header file.
//HelloWorld.h/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class HelloWorld */#ifndef _Included_HelloWorld#define _Included_HelloWorld#ifdef __cplusplusextern "C" {#endif/* * Class: HelloWorld * Method: print * Signature: ()V */JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
This header file tells us the prototype of the function that needs to be implemented using C/C ++, that is
Jniexport void jnicall java_helloworld_print (jnienv * ENV, jobject OBJ)
You only need to implement the function body in this format. The format of the function name is as follows:
Java _ classname_function name
The parameter env represents the Java Virtual Machine environment. The parameters passed by Java are very different from those passed by C. You need to call the interface provided by JVM to convert it to C type, the env method is called to complete the conversion.
The OBJ parameter represents the called object, which is equivalent to this of C ++. When the C function needs to change the member variable of the called object, this object can be operated.
4. Implement C/C ++ Functions
This part is a bit lazy, and it is not typed one by one. Instead, it is created by copying the header file, deleting useless information in the header file, and filling the function body. the C file is mainly because the JNI function names are complex and you are afraid to miss a character or miss a function. Sorry.
//HelloWorld.c#include <jni.h>#include <stdio.h>#include "HelloWorld.h"/* * Class: HelloWorld * Method: print * Signature: ()V */JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *, jobject){ printf("Hello World!\n");}
From the above we can see that the implementation of the function body is exactly the same as that of a common C/C ++ function. The difference is only the format of the function prototype.
Remember to add two header files: JNI. h and helloworld. h.
5. compile and generate library files
Gcc-I/usr/lib/JVM/Java-1.5.0-sun-1.5.0.22/include/Linux/
-I/usr/lib/JVM/Java-1.5.0-sun-1.5.0.22/include/
-FPIC-shared-O libhelloworld. So helloworld. c
During compilation, remember to add two Java paths, which are set based on the actual installation path of your Java environment. The remaining paths are the same as the common dynamic library compiling methods.
The first red box contains a common error, that is, the two parameters of the JNI function are not filled. Although they are not used here, they must be written. Otherwise, compilation fails.
//HelloWorld.c#include <jni.h>#include <stdio.h>#include "HelloWorld.h"/* * Class: HelloWorld * Method: print * Signature: ()V */JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *env, jobject obj){ printf("Hello World!\n");}
6. Run the Java program
Two common errors are circled in the box. The cause of the first error is that the generated C/C ++ dynamic library cannot be found. You need to manually specify the library path, of course, you can also copy the database to the system library file directory.
To manually specify the dynamic library path, use the parameter-djava. Library. Path.
Java-djava. Library. Path = "." helloworld
The second error occurs because a space is used before or after the "=" parameter, and the space before and after the equal sign is removed.
OK, I'm done. I finally saw the long-awaited helloworld!
7. Appendix: A simple routine
<1>. mytools. Java
//MyTools.javaclass MyTools{ private native int myAdd(int x, int y); private native int mySub(int x, int y); public static void main(String[] args){ int a = 5; int b = 7; int c = new MyTools().myAdd(a, b); int d = new MyTools().mySub(a, b); System.out.println(a + " + " + b + " = " + c); System.out.println(a + " - " + b + " = " + d); } static{ System.loadLibrary("MyTools"); }}
<2>. automatically generate the mytools. h header file
//MyTools.h/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class MyTools */#ifndef _Included_MyTools#define _Included_MyTools#ifdef __cplusplusextern "C" {#endif/* * Class: MyTools * Method: myAdd * Signature: (II)I */JNIEXPORT jint JNICALL Java_MyTools_myAdd (JNIEnv *, jobject, jint, jint);/* * Class: MyTools * Method: mySub * Signature: (II)I */JNIEXPORT jint JNICALL Java_MyTools_mySub (JNIEnv *, jobject, jint, jint);#ifdef __cplusplus}#endif#endif
<3>. Implement mytools. C in C/C ++ of the function body
//MyTools.c#include <jni.h>#include "MyTools.h"/* * Class: MyTools * Method: myAdd * Signature: (II)I */JNIEXPORT jint JNICALL Java_MyTools_myAdd (JNIEnv *env, jobject obj, jint x, jint y){ return (x + y);}/* * Class: MyTools * Method: mySub * Signature: (II)I */JNIEXPORT jint JNICALL Java_MyTools_mySub (JNIEnv *env, jobject obj, jint x, jint y){ return (x - y);}
Running result:
Note:
1. in most cases, JNI is used in Android development. The purpose of this article is to describe the most basic and simple process of using JNI in the simplest language, so the android framework is not used, A lot of things in the android framework will block our attention and cannot focus on our understanding of JNI itself. In Android, the use process of JNI is basically the same as that of Java, later, we will introduce JNI programming in Android.
2. Here we implement the use of JNI to pass simple parameters X and Y.
3. based on the above two examples, we believe that you can write your own simple JNI applications. However, the entire JNI system is quite complex. In particular, the transmission of parameters and return values will be detailed later.
<End>
JNI technical foundation (2) -- writing JNI code from scratch