1.新建一个java类并声明public native方法:
1.0 注意C语言和java的衔接:
Java的文件名必须是Java类名
C/C++的.c文件名是完全自定义的,.h文件和头文件名就是头文件名
看多了Java的朋友再回来看C/C++别搞混了。
1.1:Java文件
- new Java Project
- new Package:注意包名不要下划线
- new class
- 在新建的Java class中声明public native方法:
如:
public native String getMyStringFromJNI();
1.2:C语言编译器:实现Java方法对应的C方法(方法在头文件中)
- 在cmd下cd 到当前java类所在的src文件夹下
- 使用javah -jni命令+包名+类名 生成java类对应的c的头文件:
然后刷新Refresh即可。
注意:头文件包含C/C++的方法的声明,再在.c文件中实现其方法体即可。
1.3:返回到java类中:
- 在新建的Java class中加载动态库:即C/C++头文件
static {
//加载当前目录下的C++头文件
System.loadLibrary("native-lib");//native-lib就是C++的头文件名
}
//其中:可以用System.load("文件具体路径")的形式加载。
- 然后调用getMyStringFromJNI()方法就相当于调用对应的C语言的头文件中的用javah -jni生成的头文件中对应的方法。
2.总结:
其实JNI的实现逻辑并不复杂:
1.Java方法:要有一个函数名,并且有一个static加载动态库(即C的头文件)的声明。
2.C方法:C函数的函数名要包含在头文件中,函数的实现在.c文件中,所以要实现一个对应的头文件,还有一个C函数名。
3.然后最终实现的就是Java函数名,C/C++实现的效果。
注意:这些函数名和头文件理论上应该具有标准命名格式的。
3.Android Studio中使用JNI开发:
在Android Studio中使用JNI开发会更方便,Android Studio会自动帮你实现很多步骤,只要你在新建项目的时候,选择模板native C++即可。
下面粘贴Android Studio下的jni代码示例:
(1)Java代码层:
文件名(即类名):
MainActivity
package com.example.mynative;
import ...
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = findViewById(R.id.sample_text);
tv.setText(stringFromJNI()+"\n"+stringFromJNI1());
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
public native String stringFromJNI1();
}
(1)C++代码层:
文件名(即头文件名):
native-lib
#include <jni.h>
#include <string>
extern "C"//采用C的编译模式,不允许函数重载,保证函数名唯一,即Java函数名和C/C++函数名一一对应。
JNIEXPORT jstring JNICALL//两关键字,1.允许方法可以外部调用,2.表示jni可以调用。
//参数1:C和Java互相调用的中介,使用env->即可显示其中的函数。所以此处可以实现C中调用Java属性和方法等。
//参数2:C函数对应的java函数所在对象,这里就是this
Java_com_example_mynative_MainActivity_stringFromJNI(JNIEnv* env,jobject j/* this */) {
std::string hello = "Hello from C++ by JNI";
return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_mynative_MainActivity_stringFromJNI1(JNIEnv *env, jobject thiz) {
// TODO: implement stringFromJNI1()
std::string hello = "第二个函数返回的:Hello from C++ by JNI";
return env->NewStringUTF(hello.c_str());
}