JNI study notes 2-Java passed to CC code to output content to logcat-C code callback java method

Java passing data to C example:

public class JNI {

static{
System.loadLibrary("passdata");
}

//Pass two variables of type int to C, let C add it and return it
public native int add(int x, int y);
//pass the parameter of type String to C and process it and return it
public native String sayHelloInC(String s) ;
//Pass an array of type int to C
public native int[] arrElementsIncrease(int[] intArray);
}

Written in C language:

 

#include <jni.h>
#include <stdlib.h>

#include <android/log.h>

#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

JNIEXPORT jint JNICALL Java_com_itheima_javapassdata_JNI_add
(JNIEnv * env, jobject clazz, jint x, jint y){
return x+y; ,

















(*env)->ReleaseByteArrayElements(env, barr, ba,0);
return rtn;
}

JNIEXPORT jstring JNICALL Java_com_itheima_javapassdata_JNI_sayHelloInC
(JNIEnv * env, jobject clazz, jstring jstr){
//Call the tool method to convert the string type in java to char*
char* cstr = _JString2CStr(env,jsr);
//call strlen Get the length of the cstr string
int length = strlen(cstr);
int i;
for(i = 0;i<length;i++){
*(cstr+i) += 1;
}
return (*env)->NewStringUTF( env,cstr);
}

 

JNIEXPORT jintArray JNICALL Java_com_itheima_javapassdata_JNI_arrElementsIncrease
(JNIEnv * env, jobject clazz, jintArray jArray){
//jsize (*GetArrayLength)(JNIEnv*, jarray);
jsize length =(*env)->GetArrayLength(env,jArray);
LOGD("length = %d",length);
//jboolean iscopy;
//jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
int* arrayPointer =(*env)->GetIntArrayElements(env,jArray,NULL);
int i;
for(i = 0;i<length;i++){
*(arrayPointer+i) += 10;
}
return jArray;
}

Output content to logcat in C code

Android.mk文件增加以下内容
LOCAL_LDLIBS += -llog
C代码中增加以下内容
#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
  • define C macro definition alias #define LOG TAG "System.out" alias "System.out" LOG TAG
  • #define LOGI(...) androidlogprint(ANDROID_LOGINFO, LOGTAG, _VAARGS)
  • Aliases the  android log print function and writes the first two parameters, the first parameter priority, the second parameter TAG
  • VA ARGS _ Fixed notation for variadic arguments
  • LOGI(...) is used in the same way as printf() when called

C code callback java method (reflection)

  • ① Find the bytecode object
    • //jclass (FindClass)(JNIEnv, const char*);
    • //The path of the class where the java method to be called by the second parameter is located "com/itheima/callbackjava/JNI"
  • ② Find the method object through the bytecode object
    • //jmethodID (GetMethodID)(JNIEnv, jclass, const char, const char);
    • The second parameter bytecode object The third parameter is the name of the java method to be called by reflection The fourth parameter is the signature of the java method to be called by reflection
    • Get the method signature: javap -s The full class name of the class to get the method signature project/bin/classes Run javap
  • ③ Create a java object through bytecode (optional) If the native method and the java method to be called back are in the same class, you can directly use the java object passed by jni to call the created Method
    • jobject obj =(*env)->AllocObject(env,claz);
    • When the callback method is not in the same class as the native method, you need to manually create a java object through the newly created bytecode object
    • Then use this object to call back the java method
    • It should be noted that if the method of creating an activity object callback also contains the context, this method will not work!!! Return a null pointer exception
  • ④ Reflection call java method
    • //void (CallVoidMethod)(JNIEnv, jobject, jmethodID, ...);
    • The second parameter is the object to call the java method The third parameter is the jmethodID object to be called Optional parameters The parameters received when calling the method

example:

public class JNI {
static{
System.loadLibrary("callback");
}
private Context mContext;
public JNI(Context context){
mContext = context;
}
public native void callbackvoidmethod();

public native void callbackintmethod();

public native void callbackStringmethod ();

public native void callbackShowToast();
//C calls java empty method
public void helloFromJava(){
System.out.println("hello from java");
}
//C calls java with two int parameters Method
public int add(int x,int y) {
return x+y;
}
//C calls the method whose parameter is string in java
public void printString(String s){
System.out.println(s);
}
public void showToast(String s){
Toast.makeText(mContext, s, 0).show();
}
}

In the C file:

 

#include <jni.h>
#include <stdlib.h>
#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
/**
* 把一个jstring转换成一个c语言的char* 类型.
*/
char* _JString2CStr(JNIEnv* env, jstring jstr) {
char* rtn = NULL;
jclass clsstring = (*env)->FindClass(env, "java/lang/String");
jstring strencode = (*env)->NewStringUTF(env,"GB2312");
jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); // String .getByte("GB2312");
jsize alen = (*env)->GetArrayLength(env, barr);
jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);
if(alen > 0) { rtn
= (char*)malloc(alen+1); //"\0"
memcpy(rtn, ba , alen);
rtn[alen]=0;
}
(*env)->ReleaseByteArrayElements(env, barr, ba,0);
return rtn;
}
JNIEXPORT void JNICALL Java_com_itheima_callbackjava_JNI_callbackvoidmethod
(JNIEnv * env, jobject clazz){
//jclass ( *FindClass)(JNIEnv*, const char*);
//① Get the bytecode object
jclass claz = (*env)->FindClass(env,"com/itheima/callbackjava/JNI");
//②Get the Method object , the fourth parameter is the method signature
//jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID methodID =(*env)->GetMethodID(env,claz,"helloFromJava","()V");
//③Create an Object through the bytecode object //④Call the
method through the object
//void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
(*env)->CallVoidMethod(env,clazz, methodID);

}

JNIEXPORT void JNICALL Java_com_itheima_callbackjava_JNI_callbackintmethod
(JNIEnv * env, jobject clazz){
//① 获取字节码对象
jclass claz =(*env)->FindClass(env,"com/itheima/callbackjava/JNI");
//②获取Method对象
jmethodID methodID = (*env)->GetMethodID(env,claz,"add","(II)I");
//jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
int result =(*env)->CallIntMethod(env,clazz,methodID,3,4);
LOGD("result = %d",result);
}

JNIEXPORT void JNICALL Java_com_itheima_callbackjava_JNI_callbackStringmethod
(JNIEnv * env, jobject clazz){
//① 获取字节码对象
jclass claz =(*env)->FindClass(env,"com/itheima/callbackjava/JNI");
//② 获取Method对象
jmethodID methodid =(*env)->GetMethodID(env,claz,"printString","(Ljava/lang/String;)V");
//
jstring result =(*env)->NewStringUTF(env,"hello from c");
(*env)->CallVoidMethod(env,clazz,methodid,result);
}
JNIEXPORT void JNICALL Java_com_itheima_callbackjava_JNI_callbackShowToast
(JNIEnv * env, jobject clazz){
jclass claz =(*env)->FindClass(env,"com/itheima/callbackjava/JNI");
jmethodID methodid =(*env)->GetMethodID(env,claz,"showToast","(Ljava/lang/String;)V");
//jobject (*AllocObject)(JNIEnv*, jclass);
//Create a java object through a bytecode object Here is the object that created the mainactivity
//jobject obj =(*env)->AllocObject(env,claz);
jstring result =(*env)->NewStringUTF(env,"hello from c");
//void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
(*env)->CallVoidMethod(env, clazz,methodid,result);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325154239&siteId=291194637