19 JNI - 预处理器与JNI基础交互

82 阅读2分钟

Android Ndk 学习笔记(目录)

1 宏 相关知识点

#ifndef CLIONCPPPROJECT_T2_H // 如果没有定义这个宏  解决循环拷贝的问题
#define CLIONCPPPROJECT_T2_H // 就定义这个宏

// 第一次能够进来
// 第二次  第n此进不来    直接 解决循环拷贝的问题了

// ---------------
#ifndef isRelease // 如果没有isRelease这个宏
#define isRelease 1 // 是否是正式环境下 【我就定义isRelease这个宏】

#if isRelease == true
#define RELEASE // 正式环境下 定义RELEASE宏

#elif isRelease == false
#define DEBUG // 测试环境下  定义DEBUG宏

#endif // 结束里面的if
#endif // 结束里面的if

#endif //CLIONCPPPROJECT_T2_H // 结束外面的if
#ifndef HONG// 如果没有定义这个宏
#define HONG// 我就定义宏
#ifdef HONG// 是否定义了这个宏
for (int i = 0; i < 6; ++i) {
    cout << "HONG 1" << endl;
}
// 省略 500行 ...

#ifdef HONG// 是否定义了这个宏
for (int i = 0; i < 6; ++i) {
    cout << "HONG 2" << endl;
}
// 省略 500行 ...

#undef HONG// 取消宏的定义,下面的代码,就没法用这个宏了,相当于:没有定义过HONG宏

#ifdef HONG
cout << "你定义了HONG宏" << endl;
#else
cout << "你没有定义了HONG宏" << endl;

#endif
#endif
#endif
#endif

//宏替换

#define VALUE_I 9527
int i = VALUE_I; // 预处理阶段 宏会直接完成文本替换工作,替换后的样子:int i = 9527;

#define ADD(n1, n2) n1 + n2
int r = ADD(1+1, 2+2);
r = 6 ;

#define CHE(n1, n2) n1 * n2

r = CHE(1+1, 2+2);
//  会被替换成
r = 1+1 * 2+2;
// 计算先乘除 ,后加减 最后结果 r = 5 ;
r = 5

c++ 日志打印

#include <android/log.h>

#define TAG "info"

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)

2 JNI 基本交互

在这里插入图片描述
在这里插入图片描述

public native String stringFromJNI();
extern "C" // 无论是C还是C++ 最终是调用到 C的JNINativeInterface,所以必须采用C的方式 extern "C"
JNIEXPORT  // 标记该方法可以被外部调用(VS上不加入 运行会报错, AS上不加入运行没有问题)
jstring  // Java <---> native 转换用的   方法返回
JNICALL // 代表是 JNI标记,可以少
// java + 包名 + 类名 + 方法名 
Java_com_cn_mynativestudy_MainActivity_stringFromJNI 
(
        JNIEnv* env,   // JNIEnv 对象 ,JNI的操作都需要 JNIEnv 的函数
        jobject /* this */) {  //   MainActivity 的对象
    std::string hello = "Hello from C++";   
    return env->NewStringUTF(hello.c_str());
}
public static native void changeAge();
extern "C"
JNIEXPORT void JNICALL
// 如果 java 中 是static 静态方法 ,JNI中 者传入该方法所对应类的class jclass MainActivity
Java_com_cn_mynativestudy_MainActivity_changeAge(
JNIEnv *env, 
jclass clazz  //  MainActivity 的class 
) {

        jfieldID  j_filed = env->GetStaticFieldID(clazz,"age","I");


        env->SetStaticIntField(clazz,j_filed,22);


}

JNI 中的部分函数

 extern "C"
JNIEXPORT void JNICALL
// 如果 java 中 是普通方法 ,JNI中 者传入该方法所对应类的对象 jobject MainActivity
Java_com_cn_mynativestudy_MainActivity_changeName(JNIEnv *env, jobject thiz) {

    // 通过 jobject 对象 获取 class 对象
    jclass j_cls = env->GetObjectClass(thiz);

	// 通过  GetFieldID 函数 获取到  field  成员变量  
	//  第一个参数 ,jclass 通过转换得来 ,第二个参数 属性名 ,第三个参数 ,属性签名
    jfieldID jfieldId = env->GetFieldID(j_cls,"name","Ljava/lang/String;");
	
	//  获取成员变量的值  并强转成  jstring
    jstring  j_str = static_cast<jstring>(env->GetObjectField(thiz,jfieldId));

	//  jstring  转 char *
    char * c_str = const_cast<char *>(env->GetStringUTFChars(j_str, NULL));
    // 日志 打印
    char * TAG = "info";
    LOGD("native : %s\n", c_str);
    LOGE("native : %s\n", c_str);
    LOGI("native : %s\n", c_str);
    //创建一个 新的 jstring
    jstring  newString = env->NewStringUTF("new String ");
	// 成员变量赋值
    env->SetObjectField(thiz,jfieldId,newString);

}
extern "C"
JNIEXPORT void JNICALL
// 如果 java 中 是static 静态方法 ,JNI中 者传入该方法所对应类的class jclass MainActivity
Java_com_cn_mynativestudy_MainActivity_changeAge(JNIEnv *env, jclass clazz) {

		// 获取成员变量 GetStaticFieldID
        jfieldID  j_filed = env->GetStaticFieldID(clazz,"age","I");
        // 赋值 SetStaticIntField
        env->SetStaticIntField(clazz,j_filed,22);

}

c++ 中 调用 java中方法

public int add(int number1, int number2) {
        return number1 + number2 + 8;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_cn_mynativestudy_MainActivity_callAddMethod(JNIEnv *env, jobject thiz) {

// 获取类对象 
    jclass j_clz = env->GetObjectClass(thiz);
// 通过方法名 获取 methodid 对象
    jmethodID  j_med =  env->GetMethodID(j_clz,"add","(II)I");
// 调用该方法 
    int num = env->CallIntMethod(thiz,j_med,5,5);

	// num = 18 // 5+5+8 = 18 ;
}

在这里插入图片描述
在这里插入图片描述

    Java的引用类型  --- Lxxx/xxx/xx/类名;
    Java的String  --- Ljava/lang/String;
    Java的array  int[]  --- [I         double[][][][]  --- [[[D
    int add(char c1, char c2) ---- (CC)I
    void a()     ===  ()V