当前位置:网站首页>ndk初学习(一)

ndk初学习(一)

2022-07-07 12:10:00 v_3483608762

NDK的知识

1. 静态注册 。

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


  public native String stringFromJNI();

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

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

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 ("+++++++");

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

在上方建一个函数

void* myThread(void* a){
    
    for (int i = 0; i <9; ++i) {
    
        logd("myThread%d",i);
    }
    pthread_exit(0);
}

加了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 ("===============");

用指针传进去

void* myThread(void* a){
    
    int *num= static_cast<int *>(a);
    for (int i = 0; i <*num; ++i) {
    
        logd("myThread%d",i);
    }
    pthread_exit(0);
}

传个结构体进入线程

创建一个线程

struct moting{
    
    std::string name;
    int  age;
    bool sex;
};

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 ("===============");

然后接着传指针。

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;
}

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


JNIENV和JNIVm 的区别

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

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

		JavaVM *vm1;
    env->GetJavaVM(&vm1);
		globalVm=vm1;

vm1就有值了

或者JNI_OnLoad的第一个参数

  1. vm拿到env

主线程里

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

子线程里

原网站

版权声明
本文为[v_3483608762]所创,转载请带上原文链接,感谢
https://blog.csdn.net/v_3483608762/article/details/125624220