一、Java调用C++方法
NdkTools.java :
package com.suhang.testdemo;
public class NdkTools {
static {
System.loadLibrary("native-lib");
}
//native 表示该方法为 C++ 方法
public static native void sayHello();
}
- 先使用静态方法load library
- 在方法上按Alt+Enter,自动生成 C++ 方法代码
extern "C"
JNIEXPORT void JNICALL
Java_com_suhang_testdemo_NdkTools_sayHello(JNIEnv *env, jclass clazz) {
// TODO: implement sayHello()
LOGI("测试代码");
}
方法命名规则:
- JNIEXPORT void JNICALL : void 为返回值类型,其余两个为固定写法
- Java : 代表是Java方法
- com_suhang_testdemo : 包名
- NdkTools : 类名
- sayHello : 方法名
MainActivity.java:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NdkTools.sayHello();
}
}
执行结果:
2021-10-20 16:12:22.000 12780-12780/com.suhang.testdemo I/suhang: 测试代码
二、C++调用Java方法
2.1 静态方法
2.1.1 C++调用Java静态方法
Ndktools.java
public class NdkTools {
private static final String TAG = NdkTools.class.getSimpleName();
static {
System.loadLibrary("native-lib");
}
// C++ 方法,让两个数字相加
public static native int add(int i1, int i2);
// Java 方法,在C++方法内部调用该方法。当计算结束后,调用此方法。
public static int result(int result) {
Log.d(TAG, "result: " + result);
return result;
}
}
native-lib.cpp
extern "C"
JNIEXPORT jint JNICALL
Java_com_suhang_testdemo_NdkTools_add(JNIEnv *env, jclass clazz, jint i1, jint i2) {
// TODO: implement add()
// 1. 获取对应类
//此处传入完整的包名及类型。使用"/"代替"."
jclass cls = env->FindClass("com/suhang/testdemo/NdkTools");
// 非空判断
if (cls == NULL) { return -1; }
// 2. 获取对应方法
//第一个参数为方法所在类,第二个参数为方法名称,第三个参数为方法签名
jmethodID method = env->GetStaticMethodID(cls, "result", "(I)I");
// 非空判断
if (method == NULL) { return -1; }
// 3. 调用该方法
env->CallStaticIntMethod(cls, method, i1 + i2);
return i1 + i2;
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int add = NdkTools.add(2, 3);
Log.d(TAG, "result is : " + add);
}
}
调用结果:
2021-10-20 16:37:17.306 13107-13107/com.suhang.testdemo D/NdkTools: result: 5
2021-10-20 16:37:17.307 13107-13107/com.suhang.testdemo D/MainActivity: result is : 5
2.1.2 修改静态变量
与调用静态方法基本一致,只贴部分代码:
native-lib.cpp:
//获取目标变量
//第一个参数:类,第二个参数:变量名称,第三个参数:变量类型
jfieldID fld_name = env->GetStaticFieldID(cls_tools, "name", "Ljava/lang/String;");
if (fld_name == NULL) {
return;
}
//设置目标变量
jstring newName = env->NewStringUTF("francis");
env->SetStaticObjectField(cls_tools, fld_name, newName);
2.2 C++调用实例方法:
调用实例方法与调用静态方法基本无异,只多出两个步骤。
- 实现方法类的构造方法
- 通过构造方法,实例出方法类
NdkTools.java:
public class NdkTools {
private static final String TAG = NdkTools.class.getSimpleName();
static {
System.loadLibrary("native-lib");
}
public static native void message();
public void message(String s){
Log.d(TAG, "message: "+s);
}
}
native-lib.cpp
extern "C"
JNIEXPORT void JNICALL
Java_com_suhang_testdemo_NdkTools_message(JNIEnv *env, jclass clazz) {
// TODO: implement message()
// 1. 获取对应类
//此处传入完整的包名及类型。使用"/"代替"."
jclass cls = env->FindClass("com/suhang/testdemo/NdkTools");
// 非空判断
if (cls == NULL) { return; }
// 2. 获取对应方法
//第一个参数为方法所在类,第二个参数为方法名称,第三个参数为方法签名
jmethodID method = env->GetMethodID(cls, "message", "(Ljava/lang/String;)V");
// 非空判断
if (method == NULL) { return; }
//******************************************************************************************
//******************************************************************************************
// 3. 找到构造方法
// C++ 无法直接new出一个类来,所以需要实现一个类的构造方法,用来完成创建类的工作。
// 构造方法名称为"<init>"
jmethodID mtd_construct = env->GetMethodID(cls, "<init>", "()V");
// 非空判断
if (mtd_construct == NULL) { return; }
// 4. 实例类
jobject tools = env->NewObject(cls, mtd_construct, NULL);
// 非空判断
if (tools == NULL) {
return;
}
//******************************************************************************************
//******************************************************************************************
// 5. 执行方法
jstring test_message = env->NewStringUTF("测试 message"); //测试数据
env->CallVoidMethod(tools, method, test_message);
// 6. 删除引用
env->DeleteLocalRef(cls);
env->DeleteLocalRef(tools);
env->DeleteLocalRef(test_message);
}
执行结果:
2021-10-20 16:57:07.351 13392-13392/com.suhang.testdemo D/NdkTools: message: 测试 message
2.2.2 修改实例变量
与修改静态变量基本一致,不再赘述。