Jimmy Chen

A Programmer

(原创) JNI编程指南与规范 第四章 刻意练习

第四章之刻意练习

Practice 1

在Java侧定义两个成员变量,一个为静态成员变量,另一个为非静态成员变量。在Java侧初始化并打印这两个值,然后再native侧修改这两个值,返回到Java侧后再打印这两个值。定义这两个值一个为String类型,另一个为double类型好了。

** 下面是博主写的答案 **

Java侧代码:

class Practice1 {
    static String string;
    double dd;
    
    private native void access_modify();
    
    public static void main(String[] args) {
        Practice1 p = new Practice1();
        Practice1.string = "Hello World!";
        p.dd = 12.3;
        
        System.out.println("static string: " + Practice1.string);
        System.out.println("instance double: " + p.dd);
        
        p.access_modify();
        
        System.out.println("modify static string: " + Practice1.string);
        System.out.println("modify instance double: " + p.dd);
        
        return;     
    }
    
    static {
        System.loadLibrary("Practice1");
    }
}

native侧代码:

#include <jni.h>
#include <stdio.h>

JNIEXPORT void JNICALL native_access_modify(JNIEnv * env, jobject obj)
{
    jfieldID instance_id, static_id;
    jclass clazz;
    jstring str;
    jdouble jdd;
    const char * c_str;
    
    // 获取实例对象object所在的类
    clazz = (*env)->GetObjectClass(env, obj);
    if(clazz == NULL) {
        printf("GetObjectClass return error.\n");
        return ;
    }
    
    // 获取类实例成员ID
    instance_id = (*env)->GetFieldID(env, clazz, "dd", "D");
    if(instance_id == NULL) {
        printf("GetFiledID return error.\n");
        return;
    }
    
    // 获取静态成员ID
    static_id = (*env)->GetStaticFieldID(env, clazz, "string", "Ljava/lang/String;");
    if(static_id == NULL) {
        printf("GetStaticFieldID return error.\n");
        return;
    }
    
    // 获取类实例成员的值
    jdd = (*env)->GetDoubleField(env, obj, instance_id);
    printf("In native, jdd = %lf\n", jdd);
    // 设置类实例成员的值
    (*env)->SetDoubleField(env, obj, instance_id, 32.1);
    
    // 获取类静态成员的值
    str = (*env)->GetStaticObjectField(env, clazz, static_id);
    c_str = (*env)->GetStringUTFChars(env, str, NULL);
    if(c_str == NULL) {
        printf("GetStringUTFChars return error.\n");
        return;
    }
    printf("In native, c_str = %s\n", c_str);
    (*env)->ReleaseStringUTFChars(env, str, c_str);
    
    // 设置类静态成员的值
    str = (*env)->NewStringUTF(env, "Hello Jimmy Chen!");
    if(str == NULL) {
        printf("NewStringUTF return error.\n");
        return;
    }
    (*env)->SetStaticObjectField(env, clazz, static_id, str);
    
    return; 
}

static const JNINativeMethod gMethods[] = {
    {"access_modify", "()V", native_access_modify}
};

static jclass myClass;
static const char * ClassName = "Practice1";
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM * vm, void * reversed)
{
    JNIEnv * env = NULL;
    
    if((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) {
        printf("GetEnv return error.\n");
        return -1;
    }
    
    myClass = (*env)->FindClass(env, ClassName);
    if(myClass == NULL) {
        printf("FindClass return error.\n");
        return -1;
    }
    
    if((*env)->RegisterNatives(env, myClass, gMethods, sizeof(gMethods)/sizeof(gMethods[0])) < 0) {
        printf("RegisterNatives return error.\n");
        return -1;
    }
    
    return JNI_VERSION_1_6;
}

Practice 2

在Java侧定义四则运算加减乘除,然后在native侧获取两个double输入,分别调用Java侧的四则运算进行求值。

** 下面是博主自己写的答案 **

Java侧代码:

class Practice2 {
    private native void add_sub();
    public native void mul_div();
    
    private double add(double a, double b) {
        return a+b;
    }
    
    public double sub(double a, double b) {
        return a-b;
    }
    
    public static double mul(double a, double b) {
        return a*b;
    }
    
    private static double div(double a, double b) {
        return a/b;
    }
    
    public static void main(String args[]) {
        Practice2 p = new Practice2();
        p.add_sub();
        p.mul_div();
    }
    
    static {
        System.loadLibrary("Practice2");
    }
    
}

Native侧代码:

#include <jni.h>
#include <stdio.h>

JNIEXPORT void JNICALL native_add_sub(JNIEnv * env, jobject obj)
{
    jmethodID add_id, sub_id;
    jclass clazz;
    jdouble a, b;
    jdouble result;
    
    // 获取类
    clazz = (*env)->GetObjectClass(env, obj);
    if(clazz == NULL) {
        printf("GetObjectClass return NULL.\nm");
        return;
    }
    
    // add方法ID
    add_id = (*env)->GetMethodID(env, clazz, "add", "(DD)D");
    if(add_id == NULL) {
        printf("get add_id return NULL.\n");
        return;
    }
    
    // sub方法ID
    sub_id = (*env)->GetMethodID(env, clazz, "sub", "(DD)D");
    if(clazz == NULL) {
        printf("get sub_id return NULL,\n");
        return;
    }
    
    printf("Enter the first double number: ");
    scanf("%lf", &a);
    printf("Enter the second double number: ");
    scanf("%lf", &b);
    
    // 调用方法,传递a和b变量
    result = (*env)->CallDoubleMethod(env, obj, add_id, a, b);
    printf("Call add method, %lf + %lf = %lf\n", a, b, result);
    
    result = (*env)->CallDoubleMethod(env, obj, sub_id, a, b);
    printf("Call sub method, %lf - %lf = %lf\n", a, b, result);
    
    return;
}

JNIEXPORT void JNICALL native_mul_div(JNIEnv * env, jobject obj)
{
    jmethodID mul_id, div_id;
    jclass clazz;
    jdouble a, b;
    jdouble result;
    
    clazz = (*env)->GetObjectClass(env, obj);
    if(clazz == NULL) {
        printf("GetObjectClass return NULL.\n");
        return;
    }
    
    // 获取静态方法ID
    mul_id = (*env)->GetStaticMethodID(env, clazz, "mul", "(DD)D");
    if(mul_id == NULL) {
        printf("get mul_id return NULL.\n");
        return;
    }
    
    // 获取静态方法ID
    div_id = (*env)->GetStaticMethodID(env, clazz, "div", "(DD)D");
    if(div_id == NULL) {
        printf("get div_id return NULL.\n");
        return;
    }
    
    printf("Enter the first double number: ");
    scanf("%lf", &a);
    printf("Enter the second double number: ");
    scanf("%lf", &b);
    
    result = (*env)->CallStaticDoubleMethod(env, clazz, mul_id, a, b);
    printf("Call mul method, %lf * %lf = %lf\n", a, b, result);
    result = (*env)->CallStaticDoubleMethod(env, clazz, div_id, a, b);
    printf("Call mul method, %lf / %lf = %lf\n", a, b, result);
    
    return;
    
}

const static JNINativeMethod gMethods[] = {
    {"add_sub", "()V", native_add_sub},
    {"mul_div", "()V", native_mul_div}
};

static jclass myClass;
static const char * ClassName = "Practice2";
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM * vm, void * reversed)
{
    JNIEnv * env = NULL;
    
    if((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) {
        printf("GetEnv return error.\n");
        return -1;
    }
    
    myClass = (*env)->FindClass(env, ClassName);
    if(myClass == NULL) {
        printf("FindClass return error.\n");
        return -1;
    }
    
    if((*env)->RegisterNatives(env, myClass, gMethods, sizeof(gMethods)/sizeof(gMethods[0])) < 0) {
        printf("RegisterNatives return error.\n");
        return -1;
    }
    
    return JNI_VERSION_1_6;
}

** 此文为博主原创文章,转载请注明出处 **

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d 博主赞过: