JNI學習(一)(c和java層物件互相呼叫)
阿新 • • 發佈:2019-01-31
c層呼叫java物件
package com.example.bean;
/**
*
* java物件
* @author telenewbie
*
*/
public class JNI_cCalljava_test {
public static int num = 0;
private String name;
public static int intMethod(int n) {
num = n * n;
return num;
}
public static boolean booleanMethod (boolean bool) {
return !bool;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
#include <com_example_test_TestJava.h>
#include <jni.h>
#include <stdio.h>
#ifdef ANDROID
#include <jni.h>
#include <android/log.h>
#define LOGE(format, ...) __android_log_print(ANDROID_LOG_ERROR, "(>_<)", format, ##__VA_ARGS__)
#define LOGI(format, ...) __android_log_print(ANDROID_LOG_INFO, "(^_^)", format, ##__VA_ARGS__)
#else
#define LOGE(format, ...) printf("(>_<) " format "\n", ##__VA_ARGS__)
#define LOGI(format, ...) printf("(^_^) " format "\n", ##__VA_ARGS__)
#endif
//直接為java物件進行賦值
void test(JNIEnv * env, jobject object) {
jint square;
//在c程式碼裡面呼叫java程式碼裡面的方法
// java 反射
//1 . 找到java程式碼的 class檔案
// jclass (*FindClass)(JNIEnv*, const char*);
jclass dpclazz = (*env)->FindClass(env,
"com/example/bean/JNI_cCalljava_test");
if (dpclazz == 0) {
LOGI("find class error");
return;
}
LOGI("find class ");
//2 尋找class裡面的方法,(此處為靜態方法)
// jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID method1 = (*env)->GetStaticMethodID(env, dpclazz, "intMethod",
"(I)I");
if (method1 == 0) {
LOGI("find method1 error");
return;
}
LOGI("find method1 ");
//3 .呼叫這個方法(因為呼叫的是靜態方法傳遞類名即可,如果是物件,則需要更改方式)
// void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
square = (*env)->CallStaticIntMethod(env, dpclazz, method1, 5);
LOGI("output %d",square);
}
JNIEXPORT jstring JNICALL Java_com_example_test_TestJava_speak(JNIEnv * env,
jobject object) {
LOGI("dufresne Hello World From libhelloworld.so!");
test(env, object);
return (*env)->NewStringUTF(env, "Hello World! I am Native interface");
}
//使用反射為物件賦值,返回java層的物件
JNIEXPORT jobject JNICALL Java_com_example_test_TestJava_getMyClass(
JNIEnv * env, jobject obj, jint age, jstring name) {
jclass cls = (*env)->FindClass(env, "com/example/bean/MyClass");
if (cls == 0) {
LOGE("find MyClass Error");
return NULL;
}
jobject dpobj = (*env)->AllocObject(env, cls);
LOGI("obj=%d,dpobj=%d",obj,dpobj);
jmethodID method1 = (*env)->GetMethodID(env, cls, "setName",
"(Ljava/lang/String;)V");
if (method1 != 0) {
(*env)->CallVoidMethod(env, dpobj, method1, name);
} else {
LOGE("cant find setName method");
}
jmethodID method2 = (*env)->GetMethodID(env, cls, "setAge", "(I)V");
if (method2 != 0) {
(*env)->CallVoidMethod(env, dpobj, method2, age);
} else {
LOGE("can't find method setAge");
}
return dpobj;
}
/* This function will be call when the library first be load.
* You can do some init in the libray. return which version jni it support.
*/
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
LOGI("dufresne----->JNI_OnLoad!");
return JNI_VERSION_1_4;
}
package com.example.test;
public class TestJava {
//如果是靜態方法的話,傳遞給jni層的jobject為jclass物件,否則就是物件
public static native String speak();
public static native Object getMyClass(int age, String name);
static {
System.loadLibrary("HelloWorldJni");
}
}
android.mk
LOCAL_PATH:= $(call my-dir)
# 一個完整模組編譯
include $(CLEAR_VARS)
LOCAL_LDLIBS := -lm -llog
LOCAL_SRC_FILES:=Hello.c
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_MODULE := libHelloWorldJni
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_TAGS :=optional
include $(BUILD_SHARED_LIBRARY)