Learning JNI -- Calling C using JNI in Android
1. What is JNI:
JNIYesJava Native InterfaceIs called locally in JAVA. Java Native Interface (JNI) standards have become part of the java platform since Java1.1. It allows Java code to interact with code written in other languages. JNI was initially designed for locally compiled languages, especially C and C ++, but it does not prevent you from using other languages, as long as the call conventions are supported.
1. Benefits of using JNI:
A. You can use JNI to implement native methods and call them in JAVA programs. Generally, C functions are called in java; on the contrary, you can use C to call methods in Java, which can reuse a lot of previously written code.
B. JNI supports an invocation interface, which allows you to embed a JVM into a local program. A local program can be linked to a local library that implements JVM, and then use the "call interface" to execute the software module written in JAVA.
2. Side effects of using JNI:
A. the well-known Java portability may be damaged after JNI is used, and the program is no longer cross-platform. The reason is very simple, local methods on one operating system may not run normally on another platform, so the Java code that uses these local methods cannot run on another platform.
B. The program is no longer absolutely secure. Improper use of local code may cause the entire program to crash.
A good practice is to let the local methods called be concentrated in only a few classes of the project you write, which can reduce the coupling between Java and C code, it also improves the maintainability of the Code.
Ii. Java calls C to implement simple HelloWorld :( take Android + eclipse as an example)
Okay, it's HelloWorld again!
Here we take the Android project as an example.
Before you start, let's take a look at the basic process:
1. First create a Java file: HelloWorld. java and declare a local method. Note that you need to add a keyword native. Here we will not write his implementation. The specific implementation is handed over to C:
public native void helloworld();
2. Then we can use the javah command to generate the. h header file corresponding to the java file (used in C ):
Here I set up the environment by default, if not can see: http://www.cnblogs.com/baronzhao/archive/2012/07/10/2585181.html
Open cygwin. First, go to the src directory of the corresponding project. Here, we use cygwin to open the directory:/Cygdrive/d/Android_Workspace/JNI_day19/Exercise/src
Then execute:Javah-jni com.example.exe rcise. MainActivity, WhereCom.example.exe rcise. MainActivity is MainActivity. javaClass Name
Normally, a. h header file will be generated under the src directory:Com_example_exercise_MainActivity.h, The content is:
/* DO NOT EDIT THIS FILE - it is machine generated */#include
/* Header for class com_example_exercise_MainActivity */#ifndef _Included_com_example_exercise_MainActivity#define _Included_com_example_exercise_MainActivity#ifdef __cplusplusextern "C" {#endif/* * Class: com_example_exercise_MainActivity * Method: getStr * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_example_exercise_MainActivity_getStr(JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
In fact, the above macro definitions such as endif are not necessary. The key part is only oneInclude And JNIEXPORT jstring JNICALL Java_com_example_exercise_MainActivity_getStr (JNIEnv *, jobject );
Among them, jni. h is the header file of the corresponding type and function in c corresponding to the types and methods in java defined by jni. This is required.
Second, JNIEXPORT jstring JNICALL Java_com_example_exercise_MainActivity_getStr (JNIEnv *, jobject); this sentence can be removed except JNIEXPORT. Other statements must be kept in the same way:Return type (void here) java _ full class name (. To _) _ method name (JNIEnv * env, jobject ojb);
3. Create a folder named jni in the project, cut the generated. h file into the jni folder, and write the corresponding. c/. cpp code.
Here is a small detail, sometimes eclipse will A yellow question mark is reported here. The corresponding jni. h file cannot be found. We can right-click the project and then click AndroidTools-> AddNativeSupport, for example:
After clicking it, a dialog box is displayed:
Here, we can directly write the so file name we want to generate. c file association. Here we select "hello" and click "Finish". We found that eclipse automatically generates two new files in the jni Folder:Android. mkAndHello. cpp <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> Expires + expires/s6qo7o8L3A + CjxwPiA8L3A + CjxwcmUgY2xhc3M9 "brush: java;"> LOCAL_PATH :=$ (call my-dir) include $ (CLEAR_VARS) # It corresponds to the name of the library packaged into LOCAL_MODULE: = hello # src directory, corresponding to the file LOCAL_SRC_FILES: = hello. cpp include $ (BUILD_SHARED_LIBRARY)
This file is used to specify the rules for generating the. so file.
The hello. cpp file is the file we need to actually write c code. Here, we will implement the jstring JNICALL Java_com_example_exercise_MainActivity_getStr (JNIEnv *, jobject) in the header file.
In fact, what we need to do here is very simple. Our purpose is to return a string in this function: "hello from C! ", In fact, we need to use a method defined in jni. h:Jstring (* NewStringUTF) (JNIEnv *, const char *); It is used to return a jstring
#include
#include "com_example_err_MainActivity.h"//jstring (*NewStringUTF)(JNIEnv*, const char*);JNIEXPORT jstring JNICALL Java_com_example_err_MainActivity_helloWorld(JNIEnv * env, jobject obj) {return (*env).NewStringUTF("hello from c!");}
4. What we need to do afterwards is generate. so library file. When the system environment variable is configured, open cmd and enter the corresponding project directory. Run ndk-build to generate the corresponding library file: libhello. so.
In fact, this file will appear in the project folder:Obj/local/armeabi/Folder.
Now, the function library has been generated. The next task is to call this function.
5. Call this. so file in MainActiviy. java.In the MainActiviy. java file, we can define a Button that corresponds to the Click Event cilck. Every time you click it, we call this method to return the string "hello from c! "Printed in the form of Toast. Before that, we need to load the generated. so library file. Here, a static block is used for loading. loadLibrary ("hello"); note that we do not need to write libhello here. so, but you only need to write hello:
public class MainActivity extends Activity {public native String helloWorld();static {System.loadLibrary("hello");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void click(View view) {String helloWorld = helloWorld();System.out.println(helloWorld);Toast.makeText(getApplicationContext(), helloWorld, Toast.LENGTH_LONG).show();}}
Effect: