JNI_day02
阅读原文时间:2023年07月09日阅读:1

二级指针

指向指针变量的指针,保存指针的地址

结构体

struct Student //struct Stdent 学生结构体类型

{

int id;//成员

char name[20];

int age;

float score;

};

其中,Student为结构体名,struct Student表示结构体类型,相当于int等基本数据类型

访问结构体变量中的成员变量

(_p).id = 3 <=> stu.id <=> p->id = 3

其中->为指向运算符,用于给结构体指针变量访问其指向结构体变量中的成员变量

函数指针

表示:函数在代码段的起始地址,函数入口地址

函数指针变量:函数的入口地址

同样,函数名也代表函数的入口地址

void funA();//函数声明

int funB(int _a,int n);//函数声明

void (_pfA)();//函数指针变量,可以保存funA地址

int (_pfB)(int *,int);//函数指针变量的定义,可以保存funB函数的入口地址

结构体和联合体

结构体类型使用sizeof运算符计算出所占用空间大小为结构体中成员变量分别占用的大小总和

联合体类型使用sizeof运算符计算出所占用空间的大小为联合体中所占空间最大的那个类型

JNI开发流程

一、编码

1.创建Android工程,用native声明本地方法

2.在工程中新建jni目录,创建.c的源文件

include

/** jni规定 本地方法名 Java_调用本地方法类所在的包名_类名_方法名

  • JNIEnv * env java环境,提供函数供调用

  • jobject obj 调用本地方法的对象

  • typedef const struct JNINativeInterface* JNIEnv;

  • JNIEnv <=> struct JNINativeInterface*

  • env : JNIEnv * <=> struct JNINativeInterface**

  • (*env)->NewStringUTF();

    */

    jstring Java_com_itheima_helloworld_MainActivity_helloFromC(JNIEnv *env, jobject obj){

    //jstring (NewStringUTF)(JNIEnv, const char*); 把C字符串转化为java中字符串

    // 把C字符串转化为java中字符串

    return (*env)->NewStringUTF(env,"hello world");

    }

    二、编译

    3.在jni目录下新建Android.mk文件

    LOCAL_PATH := $(call my-dir) #提定当前路径

include $(CLEAR_VARS) #清除全局配置变量,LOCAL_XXX,除了LOCAL_PATH

LOCAL_MODULE := hello #指定生成动态库名hello,生成的动态库文件libhello.so

LOCAL_SRC_FILES := hello.c #指定生成动态库的源文件

include $(BUILD_SHARED_LIBRARY) #提定生成动态库

4.在jni目录下用ndk-build命令编译生成.so动态库(需要把ndk-build工具路径添加到系统path环境变量中)

5.在类中加载动态库

static{

System.loadLibrary("hello");//加载动态库名而不动态库文件名

}

JNI开发过程中的常见错误

a.找不到动态库

解决方案:库名错误或者生成的动态库与运行平台不符

b.找不到方法

解决方案:检查JNI的方法名是否符合规则或者Java调用的方法是否正确

javah命令的使用

a.在jdk1.6中,需要在工程的classes目录下执行,生成头文件

b.在jdk1.7中,需要在工程的src目录下执行,生成头文件

结合Eclipse和NDK的JNI开发流程

  • 1.新建Android工程,声明本地方法

  • 2.指定工程添加 add Native suport,修改其中源文件后缀为.c,在Android.mk文件中也要修改,见gif图片add ndk location2.gif

  • 3.指定jni.h头文件路径见gif图片include jni head file.gif

  • 4.进入工程src目录执行javah命令(jdk1.7),进入工程bin\classes执行javah。把jni函数声明拷贝到.c源文件中

  • 5.实现本地jni函数

  • 6.在调用类中加载动态库

    Java反射的复习

    //1.装载字节码

    Class clazz = Demo.class.getClassLoader().loadClass("Dialog");

//2.查找方法

Method method = clazz.getDeclaredMethod("showDialog", String.class);

//3.调用方法

method.invoke(clazz.newInstance(), "利用反射调用Dialog中的showDialog方法");

C调用Java中的方法(类似Java中的反射)

//1.find class

//jclass (FindClass)(JNIEnv, const char_);

jclass clazz = (_env)->FindClass(env,"com/demo/alipay01/MainActivity");

//2.get method id

//jmethodID (GetMethodID)(JNIEnv, jclass, const char_, const char_);

jmethodID methodid = (_env)->GetMethodID(env, clazz, "showDialog", "(Ljava/lang/String;)V");

//3.call void methoid

//void (CallVoidMethod)(JNIEnv, jobject, jmethodID, …);

(_env)->CallVoidMethod(env, obj, methodid, "yong hu mi ma");