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 provides a detailed description (C) of the internal examples in Section 1. For details, see Using C/C++ to Implement Java's Native Method Interface (JNI) (2) Example Detailed Explanation (C Language Version)
Section 3: Detailed explanation of examples (C++ language version)
This section details the 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 exported two functions, which corresponded one-to-one with the native methods previously defined in java.
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
C++ has a string library, so the support for strings is better, so you can first write the processing function for jstring and c++ string conversion
std::string jstring2string(JNIEnv*env, jstring jstr)
{
const char* tmpStr = env->GetStringUTFChars(jstr, nullptr);
std::string ret(tmpStr);
env->ReleaseStringUTFChars(jstr, tmpStr);
return ret;
}
jstring string2jstring(JNIEnv* env, std::string str)
{
return env->NewStringUTF(str.c_str());
}
With the support of the interface of the c++ string class, strings can be manipulated more conveniently than C character arrays, especially UTF strings:
#include <iostream>
#include <string>
#include "pers_h01c_jni_helloJni.h"
using namespace std;
std::string jstring2string(JNIEnv*env, jstring jstr) {
// 省略,见上方代码}
jstring string2jstring(JNIEnv* env, std::string str) {
// 省略,见上方代码}
JNIEXPORT void JNICALL Java_pers_h01c_jni_helloJni_helloWorld (JNIEnv * env, jobject jobj, jstring str){
const string &s = jstring2string(env, str);
string cstring0 = "jni-cpp:" + s;
cout << cstring0 << endl;
}
JNIEXPORT jstring JNICALL Java_pers_h01c_jni_helloJni_staticHelloWorld(JNIEnv * env, jclass jcls, jstring str){
const string &s = jstring2string(env, str);
string cstring0 = "input_string=" + s;
return string2jstring(env, cstring0);
}
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
Since gcc can only compile the C++ language but cannot link it, it needs to be compiled with g++. In the compilation command, just replace gcc with g++.
Compile under MacOS
export JNI_LIB_NAME=helloJniCpp
g++ -dynamiclib -I $JAVA_HOME/include -I $JAVA_HOME/include/darwin -shared -o lib/lib$JNI_LIB_NAME.dylib jni/pers_h01c_jni_helloJni_impl.cpp
In addition, the C/C++ code can also be compiled with tools such as cmake, and the C/C++ part of the code can be written using CLion IDE.
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 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