NDK学习笔记(一)

1.java方法与原生实例方法参数的关系。

java实例方法对应jobject,java静态方法对应jclass。

 public static native String stringFromJNI();
 
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_testndk_JniUtil_stringFromJNI(JNIEnv *env, jclass thiz){}
public native String stringFromJNI();

extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_testndk_JniUtil_stringFromJNI(JNIEnv *env, jobject thiz) {}

2.java与c/c++的基本数据类型关系

在这里插入图片描述

3.java应用类型与原生的关系

在这里插入图片描述

4.字符串的相关操作

把java字符串转换成C字符串

    //JNI_TRUE 返回的字符串地址指向副本
    //JNI_FALSE 回的字符串地址指向堆中的固定对象
    jboolean bo = JNI_FALSE;

    //创建字符串
    jstring ss = env->NewStringUTF("hello world");
    //将jstring转换成可操作性的字符串
    const char *str = env->GetStringUTFChars(ss, &bo);
    if (str != 0) {

        printf("111111111111111%s", str);
    }

释放字符串(不像java有垃圾回收器,申请就需要释放)

env->ReleaseStringUTFChars(ss,str);

5.数组操作

(1)创建数组

New<Type>Array
Type:对应Int、Char、Bollean等

使用实例:

    jintArray array = env->NewIntArray(10);

(2)访问数组(副本)

        //转换数组
        jint nativeARRAY[5];
        env->GetIntArrayRegion(array, 0, 5, nativeARRAY);
        //操作数组,从C数组向java数组提交所做的修改
        nativeARRAY[0] = 100;
        env->SetIntArrayRegion(array, 0, 5, nativeARRAY);

java

        int[] array = {10, 11, 12, 13, 14};
        arrayOperation(array);
        for (int i = 0; i < 5; i++) {

            Log.i("mainActivity", array[i] + "");
        }

输出结果

2020-03-14 17:35:12.173 18150-18150/com.example.testndk I/mainActivity: 100
2020-03-14 17:35:12.173 18150-18150/com.example.testndk I/mainActivity: 11
2020-03-14 17:35:12.173 18150-18150/com.example.testndk I/mainActivity: 12
2020-03-14 17:35:12.173 18150-18150/com.example.testndk I/mainActivity: 13
2020-03-14 17:35:12.175 18150-18150/com.example.testndk I/mainActivity: 14

(3)访问数组(对直接指针的操作)

        //获取直接指针
        jint *myInt = env->GetIntArrayElements(array, JNI_FALSE);
        //操作数组,提交修改并释放内存
        myInt[0] = 1555;
        env->ReleaseIntArrayElements(array, myInt, 0);

java

        int[] array = {10, 11, 12, 13, 14};
        arrayOperation(array);
        for (int i = 0; i < 5; i++) {

            Log.i("mainActivity", array[i] + "");
        }

输出结果

2020-03-14 20:45:50.064 19088-19088/com.example.testndk I/mainActivity: 1555
2020-03-14 20:45:50.065 19088-19088/com.example.testndk I/mainActivity: 11
2020-03-14 20:45:50.065 19088-19088/com.example.testndk I/mainActivity: 12
2020-03-14 20:45:50.065 19088-19088/com.example.testndk I/mainActivity: 13
2020-03-14 20:45:50.065 19088-19088/com.example.testndk I/mainActivity: 14

ReleaseIntArrayElements第三个参数mode说明。
在这里插入图片描述

6.NIO操作

    //创建直接字节缓冲区
    unsigned char *buffer = (unsigned char *) malloc(1024);
    jobject objBuffer = env->NewDirectByteBuffer(buffer, 1024);
    //获取缓冲区
    unsigned char *buffer2 = (unsigned char *)env->GetDirectBufferAddress(objBuffer);

7.访问域

extern "C" JNIEXPORT void JNICALL
Java_com_example_testndk_MainActivity_fieldOperation(
        JNIEnv *env,
        jobject /* this */, jobject obj) {

    //实例域
    //获取域id,Ljava/lang/String;
    jclass cls = env->GetObjectClass(obj);
    jfieldID fId = env->GetFieldID(cls, "size", "Ljava/lang/String;");
    //获取域
    jstring str = (jstring) env->GetObjectField(obj, fId);
    const char *c = env->GetStringUTFChars(str, JNI_FALSE);
    LOGI("%s", c);

    //静态域
    //获取域id
    jfieldID fId2 = env->GetStaticFieldID(cls, "staticSize", "Ljava/lang/String;");
    //获取域
    jstring str2 = (jstring) env->GetStaticObjectField(cls, fId2);
    const char *c2 = env->GetStringUTFChars(str2, JNI_FALSE);
    LOGI("%s", c2);
}

java

public class MyBox {

    private String size = "instance";
    private static String staticSize = "static";
}
        MyBox myBox = new MyBox();
        fieldOperation(myBox);

输出结果

2020-03-14 23:53:00.647 21624-21624/com.example.testndk I/test-jni: instance
2020-03-14 23:53:00.647 21624-21624/com.example.testndk I/test-jni: static

8.调用方法

extern "C" JNIEXPORT void JNICALL
Java_com_example_testndk_MainActivity_methodOperation(
        JNIEnv *env,
        jobject /* this */, jobject obj) {
    //获取class
    jclass cls = env->GetObjectClass(obj);
    //获取实例方法id
    jmethodID mId = env->GetMethodID(cls, "instanceMethod", "()Ljava/lang/String;");
    //调用实例方法
    jstring result = (jstring) env->CallObjectMethod(obj, mId);
    const char *c = env->GetStringUTFChars(result, JNI_FALSE);
    LOGI("%s",c);


    //获取静态方法id
    jmethodID mId2 = env->GetStaticMethodID(cls, "staticMethod", "()Ljava/lang/String;");
    //调用静态方法
    jstring result2 = (jstring) env->CallStaticObjectMethod(cls, mId2);
    const char *c2 = env->GetStringUTFChars(result2, JNI_FALSE);
    LOGI("%s",c2);
}

java

public class MyBox {


    private String instanceMethod() {

        return "instance";
   }

    private static String staticMethod() {

        return "static";
    }
}
        MyBox myBox = new MyBox();
        methodOperation(myBox);

输出内容

2020-03-15 13:50:54.937 21991-21991/com.example.testndk I/test-jni: instance
2020-03-15 13:50:54.937 21991-21991/com.example.testndk I/test-jni: static

9.域和方法的描述符

这类数据是描述符
()Ljava/lang/String;
Ljava/lang/String;

android studio的描述符配置,使得获取描述符更简单。
file→setting→tools→external tools
点击+号,name随意,其他如下:

program:$JDKPath$/bin/javap
arguments:-s -p $FileClass$
working directory:$ModuleFileDir$\build\intermediates\javac\debug\classes

点击ok,完成。
使用:点击菜单tools→external tools→你起的名字
效果:

D:\Android_develop\android_studio\jre/bin/javap -s -p com.example.testndk.MyBox
Compiled from "MyBox.java"
public class com.example.testndk.MyBox {
  public com.example.testndk.MyBox();
    descriptor: ()V

  private java.lang.String instanceMethod();
    descriptor: ()Ljava/lang/String;

  private static java.lang.String staticMethod();
    descriptor: ()Ljava/lang/String;
}

Process finished with exit code 0

10.在原生代码中使用log

#include <android/log.h>

#define LOG    "test-jni" // 这个是自定义的LOG的标识
#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG,__VA_ARGS__) // 定义LOGD类型
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG,__VA_ARGS__) // 定义LOGI类型
#define LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG,__VA_ARGS__) // 定义LOGW类型
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG,__VA_ARGS__) // 定义LOGE类型
#define LOGF(...)  __android_log_print(ANDROID_LOG_FATAL,LOG,__VA_ARGS__) // 定义LOGF类型

使用

    LOGI("%s",c);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值