JNI programming (C/C++)
Article directory
- JNI programming (C/C++)
-
- Section 1: Quick Start
- Section 2: Detailed Example (C language version)
- Section 3: Detailed explanation of examples (C++ language version)
- Section 4: JNI Data Types
- Section 5: Methods of object data such as jstring class and jobject class
- Section 6: Code examples for various JNI data types
- Appendix: Code
Section 1: Quick Start
A simple demo to quickly run through the process. For details, see Using C/C++ to Implement Java's Native Method Interface (JNI) (1) Quick Start
Section 2: Detailed Example (C language version)
This section elaborates on the inner examples in Section 1 (C)
Generate .h using Java's javah tool
The generated .h file (the path is $ProjectDir/jni/pers_h01c_jni_helloJni.h) is as follows
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class pers_h01c_jni_helloJni */
#ifndef _Included_pers_h01c_jni_helloJni
#define _Included_pers_h01c_jni_helloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: pers_h01c_jni_helloJni
* Method: helloWorld
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_pers_h01c_jni_helloJni_helloWorld
(JNIEnv *, jobject, jstring);
/*
* Class: pers_h01c_jni_helloJni
* Method: staticHelloWorld
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_pers_h01c_jni_helloJni_staticHelloWorld
(JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif
#endif
You can see that the .h exports two functions, which correspond to the native methods defined in java before.
JNIEXPORT void JNICALL Java_pers_h01c_jni_helloJni_helloWorld
(JNIEnv *, jobject, jstring);
- Corresponds to the helloWorld method in pers.h01c.jni.helloWorld
- A pointer of type JNIEnv * points to the environment object of Jni
- The parameter of jobject type corresponds to a pers.h01c.jni.helloWorld object (instance of the class) in java
- The type of parameter passed in by jstring type (helloWorld(String inputArg))
JNIEXPORT jstring JNICALL Java_pers_h01c_jni_helloJni_staticHelloWorld
(JNIEnv *, jclass, jstring);
- Corresponds to the staticHelloWorld method in pers.h01c.jni.helloWorld
- JNIEnv * and jstring ditto
- The second parameter here becomes the jclass type, which corresponds to the pers.h01c.jni.helloWorld class , because this is a static method (static) that can only operate on the class
Write the corresponding C implementation according to the generated .h
Write pers_h01c_jni_helloJni_impl.c (file path $ProjectDir/jni/pers_h01c_jni_helloJni_impl.c), including the implementation of the export method in .h
#include <stdio.h>
#include "pers_h01c_jni_helloJni.h" // 需要引入之前的.h文件
JNIEXPORT void JNICALL Java_pers_h01c_jni_helloJni_helloWorld (JNIEnv * env, jobject obj, jstring str){
const char * name = (*env) -> GetStringUTFChars(env, str, NULL); // 读取传入的UTF-编码字符串
printf("hello %s", name);
(*env) -> ReleaseStringUTFChars(env, str, name); // 释放字符串对应的内存
};
JNIEXPORT jstring JNICALL Java_pers_h01c_jni_helloJni_staticHelloWorld (JNIEnv * env, jclass cls, jstring str){
const char * name = (*env) -> GetStringUTFChars(env, str, NULL);
jstring ret = (*env) -> NewStringUTF(env, name); // 创建新的java string
return ret;
}
Instructions on the difference in the use of env
The JniEnv pointer points to the environment in the JVM virtual machine. Since the C language does not have the concept of an object, you need to use the following method to call the env method
(*env) -> GetStringUTFChars(env, str, NULL);
In C++, there is an object concept, so you can use it directly
env->GetStringUTFChars(jstr, nullptr);
Compile to C dynamic link library
The include files required for compilation include pers_h01c_jni_helloJni.h under jni/, jni.h under $JAVA_HOME/include, and jni_md.h under $JAVA_HOME/include/darwin (the reason for darwin here is that the experimental environment is the MacOS operating system , the names of other systems are different, for example, Windows may be win32)
MacOS (darwin) compilation command
export JNI_LIB_NAME=helloJni
gcc -dynamiclib -I $JAVA_HOME/include -I $JAVA_HOME/include/darwin -shared -o lib/lib$JNI_LIB_NAME.dylib jni/pers_h01c_jni_helloJni_impl.c
Note that the output file name must start with lib, which is stipulated by JNI, and the file format is dylib.
The compilation command of Windows is slightly different. On the one hand, the dynamiclib option is changed. On the other hand, the output file does not need to start with lib, and the format is dll.
gcc -Wl,--add-stdcall-alias -I"$JAVA_HOME$\include" -I"$JAVA_HOME$\include\win32" -shared -o ./lib/$JNI_LIB_NAME$.dll ./jni/pers_h01c_jni_helloJni_impl.c
Modify the Java code and test
Statically import the dynamic link library into the java class written in the first step. The library name is the same as the JNI_LIB_NAME above.
Here, the C language version is taken as an example, and the process of the C++ version is the same.
// file location: $ProjectDir/src/pers/h01c/jni/helloJni.java
package pers.h01c.jni;
public class helloJni {
static {
System.loadLibrary("helloJni"); // 注意这个库必须要在java.library.path里
}
public native void helloWorld(String inputArg);
public native static String staticHelloWorld(String inputArg);
}
If the error that the library cannot be found is reported, you need to add VM option when running the command line:
- Djava.library.path=$ProjectDir/lib/
If it is in the Intellj IDE environment, the location of $ProjectDir should be Intellj's built-in macro: $ProjectFileDir$
- Djava.library.path=$ProjectFileDir$/lib/
Section 3: Detailed explanation of examples (C++ language version)
This section focuses on the detailed description of the internal examples in Section 1 (C++). For details, see Using C/C++ to Implement Java's Native Method Interface (JNI) (3) Detailed Example (C++ Language Version)
Section 4: JNI Data Types
This section introduces some of the data types defined in JNI. For details, see Using C/C++ to Implement Java's Native Method Interface (JNI) (4) JNI Data Types
Section 5: Methods of object data such as jstring class and jobject class
This section describes in detail the operation methods of the most commonly used jstring (java.lang.String) and jobject (Object) in JNI. For details, see Using C/C++ to implement Java's Native method interface (JNI) (5) jstring class and jobject methods of object data such as class
Section 6: Code examples for various JNI data types
This section combines the content of the previous sections 1-5 to write an example JNI-C++ code that contains multiple data types. For details, see Using C/C++ to Implement Java's Native Method Interface (JNI) (6) Multiple JNI Data Type Codes example
Appendix: Code
Resource packaging link for the entire project: JNI_C/C++_Demo