入门JNI需要知道的(二)

承接上篇

我们还需要知道更多关于c语言的一些知识.

  • c语言中的字符串.
    1. c语言中用字符数组保存字符串,但需要在最后保存一个结束标志 ‘\0’.所以有效字符会比字符数组实际长度少1.
    2. c语言中的字符串由string库函数处理,需要< string.h > 声明.
    3. strlen(一个参数) 计算字符串的长度 .
    4. strcmp(两个参数) 比较字符串.
    5. 注意:
      • 字符串长度不一定是数组容量-1.
      • 字符串长度,不包括空字符.
      • 字符串的比较:逐个字符比较,直到出现字符不相等.
  • 了解堆区内存
    下图大致表示了一个进程的内存分布
    进程的内存分布
  • 堆区内存使用malloc/free

    #include <stdio.h>
    #include <stdlib.h> // malloc() free()
    
    int main(){
            int num = 0;
            int i = 0;
    
            printf("输入数组长度: ");
            scanf("%d",&num);
    
            printf("num = %d\n",num);
    
            // int a[5]
            //空间大小 : num * sizeof(int)
            //数组名:int * 
    
            int *ptr = (int *)malloc(num * sizeof(int)); //malloc是一个指针函数 , 后面会讲到
    
            for(i = 0;i < num;i++){     
                printf("输入第%d个元素的值: ",i+1);
                scanf("%d",ptr + i);    //等价于scanf("%d",&ptr[i]);
                //但是不能使用 scanf("%d",ptr++); 因为ptr自增之后,free(ptr)中的 ptr已经不是原来的ptr了 
            }
    
            for(i = 0;i < num;i++){
                printf("id[%d] = %d\n",i,ptr[i]);
            }
    
            free(ptr);//释放ptr指向的堆区空间 
            ptr = NULL;
    
            return 0;
    } 
    
  • c语言中的结构体
    相当于java中的没有方法的对象,只有变量,但是可以通过函数指针变量指向一个函数.

    struct Student{
            char name[20];
            int age;
            float score;
        }s2;
    // struct Student 这里比较特殊,需要两个写在一起才算结构体类型名,和int * 有一点类似.
    //        Student 结构体名 
    
    int main(){
    
        struct Student s1; 
    
        struct Student *ptr = &s1;
        struct Student * *pp = &ptr;
    
        s1.age = 20;
    
        //*ptr <=> s1
        //(*ptr).age = 30;
        ptr->age = 40;//结构体指针访问其指向结构体变量中成员变量 
    
        //**pp <=> *ptr <=> s1
        (**pp).age = 50;
        (*pp)->age = 60;
    
        return 0;
    } 
    
  • 函数指针

    • 函数入口地址:函数保存在text代码段中起始位置, 函数名代表函数的入口地址
    • 函数指针:函数指针变量保存函数的入口地址。
    • 特别区分函数指针与指针函数.

      1. 函数指针指向函数, 返回值由函数决定 ,它是一个指针变量.
      2. 指针函数返回指针, 它是一个函数.

        int add(int a,int b){
            return a + b;
        }
        
        int sub(int a,int b){
            return a - b;
        }
        
        int calc(int a,int b,int (*pfun)(int,int)){
            return pfun(a,b);
        }
        
        int main(){
                //int (int,int) 函数类型  
                //函数指针变量名要定义在 函数名的位置上,并且用括号括起来 
            int (*ptr)(int,int) = add; //正确的 函数指针 变量 定义
            //int * ptr (int,int); 这是一个 指针函数,返回值类型是指针类型,不能混淆
            //为了方便记忆, 星被括号括起来, 一般情况就可以看作是函数指针, ptr就是函数指针的变量名
        
            int a = 10,b = 20;
            int result = 0;
        
            result = add(a,b);//直接调用
        
            printf("result = %d\n",result); 
        
            result = ptr(a,b);
            printf("result = %d\n",result); 
        
            result = calc(a,b,add);//函数的回调 
            printf("result = %d\n",result); 
        
            result = calc(a,b,sub);
            printf("result = %d\n",result); 
        
            return 0; 
        }
        
  • typedef
    给已经存在的数据类型起别名,需要特别注意的是结构体指针类型

    int a;//a是一个标识符,a是一个变量名
    typedef int a;//a是一个标识符,a成为int类型的别名
    
    struct Student{
        ...}s1; //s1是一个标符识,s1是一个变量名
    
    typedef struct Student{
        ...}s1; //s1是一个标符识,s1变成struct Student类型别名
    
    struct Student * pstu;//pstu是一个标符识,pstu是一个结构体指针变量名
    typedef struct Student * pstu;//pstu是一个标符识,pstu是一个结构体指针类型
    
    int (*pfun)(int,int *);//pfun是一个标识符,pfun是一个函数指针变量名
    
    typedef int (*pfun)(int,int *);// pfun <=> int (*)(int,int*)
    //pfun是一个标识符,pfun是一个函数指针类型, 是int (*)(int,int*)的别名
    
  • jni头文件

    • 在了解了typedef 之后, 我们就可以看懂SDK里面的jni.h头文件了. D:\SDK\ndk-bundle\platforms\android-19\arch-arm\usr\include
      jni的头文件信息
    • jni.h头文件的作用
      • 要实现java调用c 代码, 无非就是数据的传递, 数据要传递, 那么数据类型就一定要对应起来, 相同类型的数据可以直接传递, 不同类型则需要利用函数转换. 例如
        jni头文件
        这个函数指针指向的 函数的作用就是让c里面的char * 字符串转换成java里面的jstring对象.
      • 所以, jni头文件无非就是提供给我们在JNI编程时, c 代码数据传给java ,java 代码数据传给 c 的过程中, 如果数据类型不匹配, 就需要它里面的函数进行数据的转换.
  • jni头文件里重要的结构体

    • jni头文件里有很多结构体指针类型
      这里写图片描述

      typedef struct JNINativeInterface* JNIEnv;
      
      JNIEnv <=> struct JNINativeInterface*
      
      JNIEnv * 是什么呢?
      
      JNIEnv * env; 是我们实际需要用到的参数.
      
      env : JNIEnv * <=> struct JNINativeInterface* *
      env本质上是一个二级结构体指针,若真正要访问struct JNINativeInterface*结构体中的成员,按照如下写法
      
      (**env).FindClass();
      通常按照下面的写法:
      (*env)->FindClass();
      

JNI涉及概念

  • 交叉编译: 一个平台(操作系统或处理器架构)为另一个平台编译代码.
    区别本地编译
  • 工具链: 一套编译工具,编译过程中顺序调用的一套工具.
  • 函数库: 实现某一类功能函数的集合,其中的代码已经编译成了二进制机器指令(c中非系统函数库需要我们手动链接). 提供库至少需要提供两个文件,.h头文件声明库中的函数和.so/.a库文件包含函数的具体实现.
  • 静态链接库 .a 静态库只用在静态链接过程中,将库的二进制机器指令拷贝一份.
  • 动态链接库(共享库) .so 动态库先用在动态链接过程中,记录用到哪个库的哪个函数.在程序运行之前,需要先加载动态库.

JNI开发相关工具

  • NDK: Native Development kit 本地开发工具集
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值