1. 程式人生 > >JNI學習(一)(c和java層物件互相呼叫)

JNI學習(一)(c和java層物件互相呼叫)

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)