1. 预编译器
预处理器不是编译器,预处理器主要完成文本替换的操作,主要完成文本拷贝或者替换工作。预处理器都是用 #xxx 的写法,并不是注释。预处理器主要对#
标记的内容进行处理。
1 2 3 4 5 6 7 8 9 10
| #include 导入头文件 #if if判断操作 【if的范畴 必须endif】 #elif else if #else else #endif 结束if #define 定义一个宏 #ifdef 如果定义了这个宏 【if的范畴 必须endif】 #ifndef 如果没有定义这个宏 【if的范畴 必须endif】 #undef 取消宏定义 #pragma 设定编译器的状态
|
1.1 宏函数的优缺点
- 优点:文本替换,不会造成函数的调用开销(开辟栈空间,形参压栈,函数弹栈释放。
- 缺点:会导致代码体积增大
1.2 宏函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include <iostream> using namespace std;
#define SHOW(V) cout << V << endl; #define ADD(n1, n2) n1 + n2 #define CHE(n1, n2) n1 * n2
#define LOGIN(V) if(V==1) { \ cout << "满足 你输入的是:" << V << endl; \ } else { \ cout << "不满足 你输入的是:" << V << endl; \ }
void show() {}
int main() { SHOW(8); SHOW(8.8f); SHOW(8.99);
int r = ADD(1, 2); cout << r << endl;
r = ADD(1+1, 2+2); cout << r << endl;
r = 1+1 * 2+2; cout << r << endl;
LOGIN(0); LOGIN(0); LOGIN(0); LOGIN(0); LOGIN(0); LOGIN(0);
show(); show(); show(); show(); show();
return 0; }
|
2. 操作java对象
2.1 函数签名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| //签名规则 大写 // MainActivity必须是.class javap -s -p MainActivity
Java的boolean --- Z 注意点 Java的byte --- B Java的char --- C Java的short --- S Java的int --- I Java的long --- J 注意点 Java的float --- F Java的double --- D Java的void --- V 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
javap -s -p xxx.class -s 输出xxxx.class的所有属性和方法的签名, -p 忽略私有公开的所有属性方法全部输出
|
2.2 log工具宏
1 2 3 4 5 6 7 8
| #include <android/log.h>
#define TAG "JACK"
#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.3 方法定义说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
extern "C"
JNIEXPORT
jstring
JNICALL
Java_com_jack_as_1jni_1project_MainActivity_getStringPwd (JNIEnv * env, jobject jobj) { }
|
2.4 静态函数定义
1 2 3 4 5 6
| extern "C" JNIEXPORT jstring JNICALL Java_com_jack_as_1jni_1project_MainActivity_getStringPwd2(JNIEnv *env, jclass clazz) { }
|
2.5 普通函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| extern "C" JNIEXPORT void JNICALL Java_com_jcak_as_1jni_1project_MainActivity_changeName(JNIEnv *env, jobject thiz) { jclass j_cls = env->GetObjectClass(thiz);
jfieldID j_fid = env->GetFieldID(j_cls, "name", "Ljava/lang/String;");
jstring j_str = static_cast<jstring>(env->GetObjectField(thiz ,j_fid));
char * c_str = const_cast<char *>(env->GetStringUTFChars(j_str, NULL)); LOGD("native : %s\n", c_str); LOGE("native : %s\n", c_str); LOGI("native : %s\n", c_str);
jstring jName = env->NewStringUTF("Beyond"); env->SetObjectField(thiz, j_fid, jName);
}
|
2.6 修改静态变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| extern "C" JNIEXPORT void JNICALL Java_com_jack_as_1jni_1project_MainActivity_changeAge(JNIEnv *env, jclass jcls) {
const char * sig = "I"; jfieldID j_fid = env->GetStaticFieldID(jcls, "age", sig); jint age = env->GetStaticIntField(jcls, j_fid);
age += 10; env->SetStaticIntField(jcls, j_fid, age); }
|
2.7 C调用java方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| extern "C" JNIEXPORT void JNICALL Java_com_jack_as_1jni_1project_MainActivity_callAddMethod(JNIEnv *env, jobject job) { jclass mainActivityClass = env->GetObjectClass(job);
jmethodID j_mid = env->GetMethodID(mainActivityClass, "add", "(II)I");
jint sum = env->CallIntMethod(job, j_mid, 3, 3); LOGE("sum result:%d", sum);
}
|
2.8 操作数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
|
extern "C" JNIEXPORT void JNICALL Java_com_jack_as_1jni_1project_MainActivity_testArrayAction(JNIEnv *env, jobject thiz, jint count, jstring text_info, jintArray ints, jobjectArray strs) { int countInt = count; LOGI("参数一 countInt:%d\n", countInt);
const char * textInfo = env->GetStringUTFChars(text_info, NULL); LOGI("参数二 textInfo:%s\n", textInfo);
int* jintArray = env->GetIntArrayElements(ints, NULL);
jsize size = env->GetArrayLength(ints);
for (int i = 0; i < size; ++i) { *(jintArray+i) += 100; LOGI("参数三 int[]:%d\n", *jintArray+i); }
env->ReleaseIntArrayElements(ints, jintArray, 0);
jsize strssize = env->GetArrayLength(strs); for (int i = 0; i < strssize; ++i) {
jstring jobj = static_cast<jstring>(env->GetObjectArrayElement(strs, i));
const char * jobjCharp = env->GetStringUTFChars(jobj, NULL);
LOGI("参数四 引用类型String 具体的:%s\n", jobjCharp);
env->ReleaseStringUTFChars(jobj, jobjCharp); } }
|
2.9 对象处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
extern "C" JNIEXPORT void JNICALL Java_com_jack_as_1jni_1project_MainActivity_putObject(JNIEnv *env, jobject thiz, jobject student, jstring str) { const char * strChar = env->GetStringUTFChars(str, NULL); LOGI("strChar:%s\n", strChar); env->ReleaseStringUTFChars(str, strChar);
jclass studentClass = env->GetObjectClass(student);
jmethodID setName = env->GetMethodID(studentClass, "setName", "(Ljava/lang/String;)V"); jmethodID getName = env->GetMethodID(studentClass, "getName", "()Ljava/lang/String;"); jmethodID showInfo = env->GetStaticMethodID(studentClass, "showInfo", "(Ljava/lang/String;)V");
jstring value = env->NewStringUTF("AAAA"); env->CallVoidMethod(student, setName, value);
jstring getNameResult = static_cast<jstring>(env->CallObjectMethod(student, getName)); const char * getNameValue = env->GetStringUTFChars(getNameResult, NULL); LOGE("调用到getName方法,值是:%s\n", getNameValue);
jstring jstringValue = env->NewStringUTF("静态方法你好,我是C++"); env->CallStaticVoidMethod(studentClass, showInfo, jstringValue); }
|
2.10 对象处理进阶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| extern "C" JNIEXPORT void JNICALL Java_com_jack_as_1jni_1project_MainActivity_insertObject(JNIEnv *env, jobject thiz) { const char *studentstr = "com/jack/as_jni_project/Student"; jclass studentClass = env->FindClass(studentstr);
jobject studentObj = env->AllocObject(studentClass);
jmethodID setName = env->GetMethodID(studentClass, "setName", "(Ljava/lang/String;)V"); jmethodID setAge = env->GetMethodID(studentClass, "setAge", "(I)V");
jstring strValue = env->NewStringUTF("jack"); env->CallVoidMethod(studentObj, setName, strValue); env->CallVoidMethod(studentObj, setAge, 99);
const char *personstr = "com/jack/as_jni_project/Person"; jclass personClass = env->FindClass(personstr);
jobject personObj = env->AllocObject(personClass);
jmethodID setStudent = env->GetMethodID(personClass, "setStudent", "(Lcom/jack/as_jni_project/Student;)V");
env->CallVoidMethod(personObj, setStudent, studentObj); env->DeleteLocalRef(studentClass); env->DeleteLocalRef(personClass); env->DeleteLocalRef(studentObj); env->DeleteLocalRef(personObj);
}
|
2.11 全局引用与局部引用理解
使用NewGlobalRef创建全局引用,否者都是局部引用,出栈之后,dogclass会成为悬空指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| jclass dogClass;
extern "C" JNIEXPORT void JNICALL Java_com_jack_as_1jni_1project_MainActivity_testQuote(JNIEnv *env, jobject thiz) { if (NULL == dogClass) {
const char * dogStr = "com/jack/as_jni_project/Dog"; jclass temp = env->FindClass(dogStr); dogClass = static_cast<jclass>(env->NewGlobalRef(temp)); env->DeleteLocalRef(temp); }
jmethodID init = env->GetMethodID(dogClass, "<init>", "()V"); jobject dog = env->NewObject(dogClass, init);
init = env->GetMethodID(dogClass, "<init>", "(I)V"); dog = env->NewObject(dogClass, init, 100);
init = env->GetMethodID(dogClass, "<init>", "(II)V"); dog = env->NewObject(dogClass, init, 200, 300);
init = env->GetMethodID(dogClass, "<init>", "(III)V"); dog = env->NewObject(dogClass, init, 400, 500, 600);
env->DeleteLocalRef(dog); }
extern int age; extern void show();
extern "C" JNIEXPORT void JNICALL Java_com_jack_as_1jni_1project_MainActivity_delQuote(JNIEnv *env, jobject thiz) { if (dogClass != NULL) { LOGE("全局引用释放完毕,上面的按钮已经失去全局引用,再次点击会报错"); env->DeleteGlobalRef(dogClass); dogClass = NULL; }
show(); }
|
版权声明: 此文章版权归Jack Ou所有,如有转载,请註明来自原作者