Java 中的基本數據類型包括 boolean,byte,char,short,int,long,float,double 這幾種。java
而用 C/C++ 編寫 native 代碼時,是不能直接使用 Java 的數據類型的。android
因此 JNI 提供了 jboolean、jbyte、jchar、jshort、jint、jlong、jfloat、jdouble。git
Java Type | Native Type | Description |
---|---|---|
boolean | jboolean | unsigned 8 bits |
byte | jbyte | signed 8 bits |
char | jchar | unsigned 16 bits |
short | jshort | signed 16 bits |
int | jint | signed 32 bits |
long | jlong | signed 64 bits |
float | jfloat | 32 bits |
double | jdouble | 64 bits |
void | void | N/A |
點擊每一個按鈕,將 Java 的基本數據類型傳遞到 Native,Native 代碼(C/C++)中將數據打印到日誌。
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
點擊每一個按鈕,將從 Native 代碼(C/C++)中獲取 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(C/C++) 傳遞、獲取 Java 的基本數據類型。
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); }
點擊每一個按鈕,進行測試
至此,咱們已經學會了在 Android 項目中與 Native(C/C++) 進行數據交換。github
代碼:oracle
NDKJNIday02app
參考資料:ide