JNI calling principle
I won’t go into details about the principle. In fact, it is to write a library for Java to adjust. You can search it on BaiduJava JNI. The following is the HelloWorld code test
Write a local test class
package com.my.study.cpp_jni;
/**
* 测试Java调用C++库
* <p>使用命令javac -h . NativeTest.java自动生成C头文件</p>
* <p>到jdk中的include\win32下单jni.h和jni_md.h头文件拷过来</p>
* <p>实现cpp文件</p>
* <p>编译</p>
* <p>导入</p>
* <p>配置cpp库文件</p>
* <p>System.load("D:/xxx/java/com/my/study/cpp_jni/MyLibrary.so");</p>
*
*/
public class NativeTest {
static {
/*
// 设置java.library.path路径
System.setProperty("java.library.path", "/path/to/library");
// 通过System.loadLibrary()加载库文件
System.loadLibrary("mylibrary");
*/
System.load("D:/xxx/java/com/my/study/cpp_jni/MyLibrary.dll");
}
private native void print();
public static void main(String[] args) {
new NativeTest().print();
}
}
java file format description
Use the JavaC command to generate the C language header file .h file
Use the command javac -h . NativeTest.java to automatically generate the C header file
javac -h . NativeTest.java
Generate file com_my_study_cpp_jni_NativeTest.h:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class com_my_study_cpp_jni_NativeTest */
#ifndef _Included_com_my_study_cpp_jni_NativeTest
#define _Included_com_my_study_cpp_jni_NativeTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_my_study_cpp_jni_NativeTest
* Method: print
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_my_study_cpp_jni_NativeTest_print
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
com_my_study_cpp_jni_NativeTest.h file format description
Copy the jni.h and win32/jni_md.h header files in the JDK include directory to the same path
Modify #include <jni.h> in the com_my_study_cpp_jni_NativeTest.h file to #include "jni.h" to avoid searching for C/C++ libraries
NativeTest.cpp implements C header file functions
#include<iostream>
#include "com_my_study_cpp_jni_NativeTest.h"
using namespace std;
JNIEXPORT void JNICALL Java_com_my_study_cpp_jni_NativeTest_print(JNIEnv *, jobject) {
cout << "Hello Word JNI" << endl;
}
Compile C++ library files
Compile C source code and create native libraries
//Compile C language library
// gcc -ID:\xxx\Java\Java8\jdk\include\ -ID:\xxx\Java\Java8\jdk\include \win32\ NativeTest.c -shared -o MyLibrary.so
// Compile C++ library
// g++ -ID:\xxx\Java\Java8\jdk \include\ -ID:\xxx\Java\Java8\jdk\include\win32\ NativeTest.cpp -shared -o MyLibrary.so
// gcc -I means to represent the following directory as Directory of the nth header file
Execute test and report error
Solve the error problem and confirm whether the gcc and g++ versions are 32 or 64 bits
It is better to install vs directly for testing, because I spent several hours on the problem of not being able to find the library file. It is better to install vs directly. After installing vs, the dll library will be generated in a few minutes a> Here is the file structure just created based on the corresponding header file and cpp implementation file. The files are For the above file, just put the file in the corresponding location
Here I use VS2022 to generate a dynamic link library, install it and create a C++ project
By the way, remove the pch.h precompiled header here, because it is not used, otherwise it will keep reporting errors.
Use vs to generate a dynamic link library, and put the generated code in the root directory of drive D to facilitate testing. Modify the Java test code. Here you can see that the dynamic link library I generated using the g++ instruction is smaller than the dynamic link library generated using vs. , indicating that there is something missing in the dynamic link library generated using instructions. I am not familiar with C++, so I used vs to generate it here.
/**
* 测试Java调用C++库
* <p>使用命令javac -h . NativeTest.java自动生成C头文件</p>
* <p>到jdk中的include\win32下单jni.h和jni_md.h头文件拷过来</p>
* <p>实现cpp文件</p>
* <p>编译</p>
* <p>导入</p>
* <p>配置cpp库文件</p>
* <p>System.load("D:/xxx/java/com/my/study/cpp_jni/_013_Cpp_VS_Dynamic_Link_Lib.dll");</p>
* <p>System.loadLibrary("_013_Cpp_VS_Dynamic_Link_Lib");//不加dll</p>
* Can't load IA 32-bit .dll on a AMD 64-bit platform:需要下载64位cpp编译器,不同cpu编译器不同
*/
public class NativeTest {
static {
System.load("D:/_013_Cpp_VS_Dynamic_Link_Lib.dll");
}
private native void print();
public static void main(String[] args) {
new NativeTest().print();
}
}
idea running test:
Here you can see the string Hello World JNI printed by running C++ compilation, it succeeded, spread the flowers
Summarize:
- Create a Java file and mark the function with native
- Generate .h header file
- Copy the jni.h, jni_md.h files and adjust the file reference position
- Implement header files
- Generate dynamic link library (VS is used here)
- Java call