• ndk初学习(一)


    NDK的知识

    1. 静态注册 。

    为什么要有静态注册呢,是因为java层和so层的函数需要一一对应,不会找错了。比如下面的。

    
      public native String stringFromJNI();
    
    • 1
    • 2

    那是怎么样对应起来的呢。

    是通过跳转的函数名字,非常的有规律

    Java_com_example_demonndk_MainActivity_stringFromJNI

    是java,然后包名,然后类名,然后才是名字。这就是静态注册。


    JNIEnv env:像是jni的环境 ,可以用它来调用c层的java。或者是java的数据类型到c的数据类型,c数据到java数据类型的数据转换。


    第一个参数,jobject:像是this指针,知道是那个地方调用了so层的这个函数


    第二个参数,jclass和jobject的区分:当所声明Native方法是静态方法时,对应参数jclass

    ,因为静态方法不依赖对象实例,而依赖于类,所以参数中传递的是一个jclass
    类型。相反,如果声明的Native方法时非静态方法时,那么对应参数是jobject

    extern "C" JNIEXPORT jstring JNICALL 告诉是以c的方式进行

    静态注册函数必须是导出函数 JNIEXPORT

    LOGD输出 头部引入#include <android/log.h> 就可以使用__android_log_print(3,“moting”,__VA_ARGS__)了;

    简化的可以为logd
    就可以直接用了

    logd(“hello”);


    创建线程

    pthread_t pthread;
        //int pthread_create(pthread_t* __pthread_ptr, pthread_attr_t const* __attr, void* (*__start_routine)(void*), void*);
        pthread_create(&pthread, nullptr,myThread, nullptr);
    		logd ("+++++++");
    
    • 1
    • 2
    • 3
    • 4

    先有一个线程变量,然后创建线程。

    在上方建一个函数

    void* myThread(void* a){
        for (int i = 0; i <9; ++i) {
            logd("myThread%d",i);
        }
        pthread_exit(0);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    加了pthread_join(pthread, nullptr) 就是先执行线程里的,然后执行下面的代码。

    传个数字进线程

    pthread_t pthread;
        int num=4;
        //int pthread_create(pthread_t* __pthread_ptr, pthread_attr_t const* __attr, void* (*__start_routine)(void*), void*);
        pthread_create(&pthread, nullptr, myThread, &num);
        pthread_join(pthread, nullptr);
        logd ("===============");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    用指针传进去

    void* myThread(void* a){
        int *num= static_cast<int *>(a);
        for (int i = 0; i <*num; ++i) {
            logd("myThread%d",i);
        }
        pthread_exit(0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    传个结构体进入线程

    创建一个线程

    struct moting{
        std::string name;
        int  age;
        bool sex;
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    moting aaa;
        aaa.name="moting";
        aaa.age=3;
        aaa.sex= true;
    
        pthread_t pthread;
        //int pthread_create(pthread_t* __pthread_ptr, pthread_attr_t const* __attr, void* (*__start_routine)(void*), void*);
        pthread_create(&pthread, nullptr, myThread, &aaa);
        pthread_join(pthread, nullptr);
        logd ("===============");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    然后接着传指针。

    c语言返回值很少用,


    so中各种函数的执行时机

    init -》 init_array-》 jni_onload


    jnionload的重写

    JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){
        JNIEnv *env= nullptr;
        if (vm->GetEnv((void **)&env,JNI_VERSION_1_6)!=JNI_OK){
            logd("getenv filed");
        }
        logd("JNI_Onload%p",env);
        return JNI_VERSION_1_6;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    一个so中可以没有JNI_ONLOAD,比如创建一个新线程。必须返回JNI的版本


    JNIENV和JNIVm 的区别

    JNIENV和JNIVm, 定义了一个全局变量JavaVM* globalVM;

    如何使用env调用vm,函数第一个参数是env

    		JavaVM *vm1;
        env->GetJavaVM(&vm1);
    		globalVm=vm1;
    
    • 1
    • 2
    • 3

    vm1就有值了

    或者JNI_OnLoad的第一个参数

    1. vm拿到env

    主线程里

    if (vm->GetEnv((void **)&env,JNI_VERSION_1_6)!=JNI_OK){
            logd("getenv filed");
        }
    
    • 1
    • 2
    • 3

    子线程里

  • 相关阅读:
    数据结构-单链表
    融云&艾瑞发布《政企数智办公平台行业研究报告》,解读数智化时代的办公新趋势
    港科夜闻|国务院发文指出将打造重大科技创新平台,稳步推进粤港澳教育合作,加快与香港科大、中科院共建省实验室...
    EasyExcel导入/导出Excel文件
    ARM-day2
    Jquery data-属性的获取与使用
    Eureka架构篇 - 服务续约与自我保护机制
    MySQL简介
    由阿里三位专家撰写:数据库高效优化:架构、规范SQL技巧文档
    Java秒杀系统方案优化
  • 原文地址:https://blog.csdn.net/v_3483608762/article/details/125624220