Android NDK JNI 入门笔记-day02-基本数据类型数据传递

* Android NDK JNI 入门笔记目录 *

Java & JNI 基本数据类型

Java 中的基本数据类型包括 boolean,byte,char,short,int,long,float,double 这几种。

而用 C/C++ 编写 native 代码时,是不能直接使用 Java 的数据类型的。

所以 JNI 提供了 jboolean、jbyte、jchar、jshort、jint、jlong、jfloat、jdouble。

Java 基本数据类型与 JNI 数据类型的映射关系

Java TypeNative TypeDescription
booleanjbooleanunsigned 8 bits
bytejbytesigned 8 bits
charjcharunsigned 16 bits
shortjshortsigned 16 bits
intjintsigned 32 bits
longjlongsigned 64 bits
floatjfloat32 bits
doublejdouble64 bits
voidvoidN/A

基本数据类型传递-练习工程

Day02 创建新项目

Java -> Native

点击每个按钮,将 Java 的基本数据类型传递到 Native,Native 代码(C/C++)中将数据打印到日志。

java-to-native

JavaToNativeActivity.java

public class JavaToNativeActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_java_to_native);
        setTitle("Java -> Native");
    }

    public void booleanTest(View view) {
        NativeUtil.javaBooleanToNative(true);
        NativeUtil.javaBooleanToNative(false);
    }

    public void byteTest(View view) {
        NativeUtil.javaByteToNative(Byte.MIN_VALUE);
        NativeUtil.javaByteToNative(Byte.MAX_VALUE);
        NativeUtil.javaByteToNative(Byte.parseByte("123"));
    }

    public void charTest(View view) {
        NativeUtil.javaCharToNative(Character.MIN_VALUE);
        NativeUtil.javaCharToNative(Character.MAX_VALUE);
        NativeUtil.javaCharToNative('A');
        NativeUtil.javaCharToNative('B');
        NativeUtil.javaCharToNative('C');
    }

    public void shortTest(View view) {
        NativeUtil.javaShortToNative(Short.MIN_VALUE);
        NativeUtil.javaShortToNative(Short.MAX_VALUE);
        NativeUtil.javaShortToNative(Short.parseShort("999"));
    }

    public void intTest(View view) {
        NativeUtil.javaIntToNative(Integer.MIN_VALUE);
        NativeUtil.javaIntToNative(Integer.MAX_VALUE);
        NativeUtil.javaIntToNative(Integer.parseInt("999999"));
    }

    public void longTest(View view) {
        NativeUtil.javaLongToNative(Long.MIN_VALUE);
        NativeUtil.javaLongToNative(Long.MAX_VALUE);
        NativeUtil.javaLongToNative(Long.parseLong("999999999"));
    }

    public void floatTest(View view) {
        NativeUtil.javaFloatToNative(Float.MIN_VALUE);
        NativeUtil.javaFloatToNative(Float.MAX_VALUE);
        NativeUtil.javaFloatToNative(999999.8F);
    }

    public void doubleTest(View view) {
        NativeUtil.javaDoubleToNative(Double.MIN_NORMAL);
        NativeUtil.javaDoubleToNative(Double.MAX_VALUE);
        NativeUtil.javaDoubleToNative(999999999.8);
    }

}

NativeUtil.java

public class NativeUtil {

    static {
        System.loadLibrary("native-lib");
    }

    public native static void javaBooleanToNative(boolean value);

    public native static void javaByteToNative(byte value);

    public native static void javaCharToNative(char value);

    public native static void javaShortToNative(short value);

    public native static void javaIntToNative(int value);

    public native static void javaLongToNative(long value);

    public native static void javaFloatToNative(float value);

    public native static void javaDoubleToNative(double value);

}

native-lib.cpp

#include <jni.h>
#include <string>
#include <android/log.h>
#include <math.h>

#define LOG_TAG  "C_TAG"
#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
//LOGD("hello.length=%d",helloLen);

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaBooleanToNative(JNIEnv *env, jclass clazz, jboolean value) {
    LOGD("Java Boolean: %d", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaByteToNative(JNIEnv *env, jclass clazz, jbyte value) {
    LOGD("Java Byte: %d", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaCharToNative(JNIEnv *env, jclass clazz, jchar value) {
    LOGD("Java Char: %d", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaShortToNative(JNIEnv *env, jclass clazz, jshort value) {
    LOGD("Java Short: %d", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaIntToNative(JNIEnv *env, jclass clazz, jint value) {
    LOGD("Java Int: %d", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaLongToNative(JNIEnv *env, jclass clazz, jlong value) {
    LOGD("Java Long: %lld", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaFloatToNative(JNIEnv *env, jclass clazz, jfloat value) {
    LOGD("Java Float: %f", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaDoubleToNative(JNIEnv *env, jclass clazz, jdouble value) {
    LOGD("Java Double: %lf", value);
}

点击每个按钮,在 Logcat 中查看输出日志

D/C_TAG: Java Boolean: 1
D/C_TAG: Java Boolean: 0
D/C_TAG: Java Byte: -128
D/C_TAG: Java Byte: 127
    Java Byte: 123
D/C_TAG: Java Char: 0
    Java Char: 65535
    Java Char: 65
    Java Char: 66
    Java Char: 67
D/C_TAG: Java Short: -32768
D/C_TAG: Java Short: 32767
    Java Short: 999
D/C_TAG: Java Int: -2147483648
    Java Int: 2147483647
    Java Int: 999999
D/C_TAG: Java Long: -9223372036854775808
    Java Long: 9223372036854775807
    Java Long: 999999999
D/C_TAG: Java Float: 0.000000
    Java Float: 340282346638528859811704183484516925440.000000
    Java Float: 999999.812500
D/C_TAG: Java Double: 0.000000
    Java Double: 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
    Java Double: 999999999.800000

Java <- Navive

点击每个按钮,将从 Native 代码(C/C++)中获取 Java 的基本数据类型。

native-to-java

NativeToJavaActivity.java

public class NativeToJavaActivity extends AppCompatActivity {

    private TextView booleanText;
    private TextView byteText;
    private TextView charText;
    private TextView shortText;
    private TextView intText;
    private TextView longText;
    private TextView floatText;
    private TextView doubleText;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_native_to_java);
        setTitle("Native -> Java");

        booleanText = findViewById(R.id.boolean_text);
        byteText = findViewById(R.id.byte_text);
        charText = findViewById(R.id.char_text);
        shortText = findViewById(R.id.short_text);
        intText = findViewById(R.id.int_text);
        longText = findViewById(R.id.long_text);
        floatText = findViewById(R.id.float_text);
        doubleText = findViewById(R.id.double_text);
    }

    public void booleanTest(View view) {
        boolean value = NativeUtil.javaBooleanFromNative();
        booleanText.setText("value = " + value);
    }

    public void byteTest(View view) {
        byte value = NativeUtil.javaByteFromNative();
        byteText.setText("value = " + value);
    }

    public void charTest(View view) {
        char value = NativeUtil.javaCharFromNative();
        charText.setText("value = " + value);
    }

    public void shortTest(View view) {
        short value = NativeUtil.javaShortFromNative();
        shortText.setText("value = " + value);
    }

    public void intTest(View view) {
        int value = NativeUtil.javaIntFromNative();
        intText.setText("value = " + value);
    }

    public void longTest(View view) {
        long value = NativeUtil.javaLongFromNative();
        longText.setText("value = " + value);
    }

    public void floatTest(View view) {
        float value = NativeUtil.javaFloatFromNative();
        floatText.setText("value = " + value);
    }

    public void doubleTest(View view) {
        double value = NativeUtil.javaDoubleFromNative();
        doubleText.setText("value = " + value);
    }

}

NativeUtil.java

public class NativeUtil {

    static {
        System.loadLibrary("native-lib");
    }
    
    public native static boolean javaBooleanFromNative();

    public native static byte javaByteFromNative();

    public native static char javaCharFromNative();

    public native static short javaShortFromNative();

    public native static int javaIntFromNative();

    public native static long javaLongFromNative();

    public native static float javaFloatFromNative();

    public native static double javaDoubleFromNative();

}

native-lib.cpp

#include <jni.h>
#include <string>
#include <android/log.h>
#include <math.h>

#define LOG_TAG  "C_TAG"
#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
//LOGD("hello.length=%d",helloLen);

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaBooleanFromNative(JNIEnv *env, jclass clazz) {
    return JNI_TRUE;
}

extern "C"
JNIEXPORT jbyte JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaByteFromNative(JNIEnv *env, jclass clazz) {
    return 123;
}

extern "C"
JNIEXPORT jchar JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaCharFromNative(JNIEnv *env, jclass clazz) {
    return 'A';
}

extern "C"
JNIEXPORT jshort JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaShortFromNative(JNIEnv *env, jclass clazz) {
    return 999;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaIntFromNative(JNIEnv *env, jclass clazz) {
    return 999999;
}

extern "C"
JNIEXPORT jlong JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaLongFromNative(JNIEnv *env, jclass clazz) {
    return 999999999;
}

extern "C"
JNIEXPORT jfloat JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaFloatFromNative(JNIEnv *env, jclass clazz) {
    return 999999.8;
}

extern "C"
JNIEXPORT jdouble JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaDoubleFromNative(JNIEnv *env, jclass clazz) {
    return 999999999.8;
}

点击每个按钮,进行测试

native-to-java-result

Java <-> Native

点击每个按钮,将和 Native(C/C++) 传递、获取 Java 的基本数据类型。

java-and-native

JavaNativeActivity.java

public class JavaNativeActivity extends AppCompatActivity {

    private TextView charConcatText;
    private TextView sumText;
    private TextView twoExpText;
    private TextView calcMoneyText;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_java_native);
        setTitle("Java <-> Native");

        charConcatText = findViewById(R.id.char_concat_text);
        sumText = findViewById(R.id.sum_text);
        twoExpText = findViewById(R.id.two_exp_text);
        calcMoneyText = findViewById(R.id.calc_money_text);
    }


    public void charConcatTest(View view) {
        String value = NativeUtil.charConcatTest('A', 'B', 'C');
        charConcatText.setText("A+B+C=" + value);
    }

    public void sumTest(View view) {
        int numOne = 123;
        int numTwo = 456;
        int value = NativeUtil.sumText(numOne, numTwo);
        sumText.setText(numOne + "+" + numTwo + "=" + value);
    }

    public void twoExpTest(View view) {
        int value = NativeUtil.twoExpTest(10);
        twoExpText.setText("2^10=" + value);
    }

    public void calcMoneyTest(View view) {
        double apple = 12.4;
        double banana = 99.8;
        double orange = 101.1;
        String value = NativeUtil.calcMoneyTest(apple, banana, orange);
        calcMoneyText.setText(value);
    }

}

NativeUtil.java

public class NativeUtil {

    static {
        System.loadLibrary("native-lib");
    }

    public native static String charConcatTest(char a, char b, char c);

    public native static int sumText(int i, int j);

    public native static int twoExpTest(int exp);

    public native static String calcMoneyTest(double v, double v1, double v2);
    
}

native-lib.cpp

#include <jni.h>
#include <string>
#include <android/log.h>
#include <math.h>

#define LOG_TAG  "C_TAG"
#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
//LOGD("hello.length=%d",helloLen);


extern "C"
JNIEXPORT jstring JNICALL
Java_com_ihubin_ndkjni_NativeUtil_charConcatTest(JNIEnv *env, jclass clazz, jchar a, jchar b,
                                                 jchar c) {
    char charArray[4];
    charArray[0] = a;
    charArray[1] = b;
    charArray[2] = c;
    charArray[3] = '\0';
    return env->NewStringUTF(charArray);
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_ihubin_ndkjni_NativeUtil_sumText(JNIEnv *env, jclass clazz, jint i, jint j) {
    return i + j;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_ihubin_ndkjni_NativeUtil_twoExpTest(JNIEnv *env, jclass clazz, jint exp) {
    return pow(2, exp);
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_ihubin_ndkjni_NativeUtil_calcMoneyTest(JNIEnv *env, jclass clazz, jdouble v, jdouble v1,
                                                jdouble v2) {
    double totalMoney = v + v1 + v2;
    char *resultStr = new char();
    sprintf(resultStr, "总计:%f", totalMoney);
    return env->NewStringUTF(resultStr);
}

点击每个按钮,进行测试

java-and-native-result

至此,我们已经学会了在 Android 项目中与 Native(C/C++) 进行数据交换。


代码:

NDKJNIday02

参考资料:

Oracle - JNI Types and Data Structures

JNI 打印 log 信息


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值