当前位置: 首页 > wzjs >正文

网站开发程序设计工程竣工验收公示网

网站开发程序设计,工程竣工验收公示网,沈阳信息港,电商平台开发Android之JNI详解 简介创建项目注册动态注册静态注册 关键词解读基础数据类型引用java对象JNI引用与释放cmake配置文件 简介 JNI(Java Native Interface) 是 Java 提供的一种编程框架,用于在 Java 应用程序中调用和与用其他编程语言&#xf…

Android之JNI详解

  • 简介
  • 创建项目
  • 注册
    • 动态注册
    • 静态注册
  • 关键词解读
  • 基础数据类型
  • 引用java对象
  • JNI引用与释放
  • cmake配置文件

简介

JNI(Java Native Interface) 是 Java 提供的一种编程框架,用于在 Java 应用程序中调用和与用其他编程语言(如 C、C++ 等)编写的本地代码(Native Code)进行交互。它允许 Java 程序访问操作系统或硬件提供的底层功能。

创建项目

  1. 在AS中选择Native C++创建项目
    在这里插入图片描述
  2. 项目结构
  • native.cpp:实现本地代码(Native Code)的C++源文件。
  • CmakeList.txt:是 CMake 工具使用的配置文件,用于指定如何构建一个 C/C++ 项目。CMake 是一个跨平台的构建系统生成器,它可以根据 CMakeLists.txt 文件生成适合特定平台和编译器的构建文件。
    在这里插入图片描述

注册

动态注册

  1. 简介:与静态注册不同,动态注册通过调用 JNI 提供的RegisterNatives函数,在程序运行时显式地注册本地方法。
  2. 实现步骤
    重要点:构建JNINativeMethod结构体:
typedef struct {const char* name; // java类对应的方法名const char* signature;	//函数签名void*       fnPtr;	//cpp方法的指针函数
} JNINativeMethod;
  • 步骤一:
package com.hzh.jnidemo;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {static {System.loadLibrary("jnidemo");}public native String stringFromJNI();public native String jniTest();
}
  • 步骤二:
//cpp交互方法,这里是属于native的命名
jstring native_stringFromJNI(JNIEnv *env,jobject thiz){return env->NewStringUTF("动态注册成功!");
}
jstring native_jniTest(JNIEnv *env, jobject thisz) {std::string str = "动态注册成功!";return env->NewStringUTF(str.c_str());
}// 需要动态注册native方法的类名
static const char *mClassName = "com/hzh/jnidemo/MainActivity";// 动态注册函数结构数组
static const JNINativeMethod methods[] = {{"jniTest",	//对应java交互类的方法名"()Ljava/lang/String;", //对应方法名的函数签名(jstring *) native_jniTest //对应cpp交互的指针函数},{"stringFromJNI","()Ljava/lang/String;",(void *) native_stringFromJNI}
};JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {JNIEnv* env = NULL;// 1. 获取 JNIEnv,这个地方要注意第一个参数是个二级指针int result = vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);// 2. 是否获取成功if(result != JNI_OK){return JNI_VERSION_1_6;}// 3. 注册方法,通过FindClass寻找jclass classMainActivity = env->FindClass(mClassName);//RegisterNatives 函数接受三个参数://jclass clazz:Java 类的引用。//const JNINativeMethod* methods:指向 JNINativeMethod 结构体数组的指针,描述 Java 方法与本地方法的映射关系。//jint nMethods:映射关系的数量。result = env->RegisterNatives(classMainActivity,methods, 2);if(result != JNI_OK){return JNI_VERSION_1_2;}return JNI_VERSION_1_6;
}

JNI_OnLoad是在初始化的时候调用,参考activity的生命周期,通过FindClass找到对应的class,最后通过RegisterNatives来实现动态注册。需要留意的是JNINativeMethod结构体以及RegisterNatives的参数。

静态注册

  1. 简介:通过 JNI 规范中约定的命名规则,将 Java 方法与本地(Native)方法的实现直接映射。这种映射关系在编译时由编译器根据方法名和签名自动生成。
  2. Native命名规则:遵循Java_包名_类名_方法名的格式,包咯面的"."需要转换成“_”,例如Java 类 com.hzh.jnidemo中的方法 MainActivity,对应的 C/C++ 函数名应为com_hzh_jnidemo_MainActivity。
  3. 原理:Java 编译器会根据 native 方法的声明生成方法签名,而 C/C++ 编译器会根据命名规则生成符号表。JVM 在加载类时,通过方法签名匹配符号表中的函数名,完成绑定。
  4. 实现步骤
  • Java端的实现如下:
    通过System.loadLibrary(“*****”)进行加载交互。
package com.hzh.jnidemo;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {static {System.loadLibrary("jnidemo");}...public native String stringFromJNI();
}
  • Native端的实现:
#include <jni.h>
#include <string>extern "C" JNIEXPORT jstring JNICALL
//*遵循命名规则实现方法*
Java_com_hzh_jnidemo_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */) {std::string hello = "Hello from C++";return env->NewStringUTF(hello.c_str());
}

关键词解读

  • extern “C”:在 c++ 中可以使用使用 c 代码
  • JNIEXPORT:是一个宏,用于导出本地方法。
  • JNICALL:是一个宏,用于指定调用约定(Calling Convention),通常是个空的宏定义。
  • JNIEnv:是一个指向JNI函数的指针结构体。
    作用:调用JNI函数,如创建Java对象、访问Java字段、调用Java方法等。
    示例:
JNIEnv *env;
jclass clazz = (*env)->FindClass(env, "class");
  • JavaVM:一个指向Java虚拟机的指针,表示整个JVM实例。
  • jclass:表示Java类的引用。
  • jobject:表示Java对象的引用。
  • jmethodID:表示Java方法的标识符。
  • jfieldID:表示Java字段的标识符。

基础数据类型

!](https://i-blog.csdnimg.cn/direct/1bc956b2ab584e4da6e609f6578af899.png)

引用类型
在这里插入图片描述
类型签名

在这里插入图片描述

  • 简介:是用于描述 Java 方法或字段的特定字符串。JNI 签名是方法描述符的一部分,它包含了方法的参数类型和返回值类型,确保本地代码能够正确调用 Java 方法或访问 Java 字段。每次GetMethodID 或 GetFieldID或者返回数据都会用到。
  • 签名格式:
    方法签名的格式为:(参数类型签名)返回值类型签名
    示例:
int add(int a, int b)(II)I
String getName()()Ljava/lang/String;
void print(String message)(Ljava/lang/String;)V

引用java对象

Field/Method ID:JNIEvn 操作 java 对象时会使用 java 中的反射,引用某个属性都需要 field 和 method 的 id,而id都是指针类型。
实现步骤:

  1. 获取 JNIEnv 指针:
  2. 查找类:
  • 使用 FindClass 函数获取 Java 类的引用。
  • 获取方法 ID 或字段 ID:
  • 使用 GetMethodID 或 GetFieldID 获取方法或字段的标识符。
  1. 操作 Java 对象:
  • 使用 NewObject、CallObjectMethod、SetObjectField 等函数创建或操作 Java 对象。

示例:获取一个class的getName()方法

extern "C" JNIEXPORT jstring JNICALL
Java_com_hzh_jnidemo_MainActivity_stringFromJNI(JNIEnv *env, jobject thiz) {// 1. 获取 thiz 的 class,也就是 java 中的 Class 信息jclass thisclazz = env->GetObjectClass(thiz);// 2. 根据 Class 获取 getClass 方法的 methodID//GetMethodID/GetFieldI的参数://jclass//filed/methon name //类型签名: JNI 使用 jvm 的类型签名jmethodID mid_getClass = env->GetMethodID(thisclazz, "getClass", "()Ljava/lang/Class;");// 3. 执行 getClass 方法,获得 Class 对象jobject clazz_instance = env->CallObjectMethod(thiz, mid_getClass);// 4. 获取 Class 实例jclass clazz = env->GetObjectClass(clazz_instance);// 5. 根据 class  的 methodIDjmethodID mid_getName = env->GetMethodID(clazz, "getName", "()Ljava/lang/String;");// 6. 调用 getName 方法jstring name = static_cast<jstring>(env->CallObjectMethod(clazz_instance, mid_getName));......}

JNI引用与释放

  • 局部引用(Local Reference):参考java 中的局部变量
    // 查找类jclass myClass = (*env)->FindClass(env, "com/hzh/jnidemo/MainActivity");// 获取方法 IDjmethodID myMethod = (*env)->GetMethodID(env, myClass, "stringFromJNI", "()Ljava/lang/String");// 调用 Java 方法(*env)->CallVoidMethod(env, obj, myMethod);
  • 全局引用(Global Reference):参考java 中的全局变量
 	// 创建局部引用jobject localRef = (*env)->NewObject(env, /* 类和方法 ID 略 */);// 创建全局引用globalRef = (*env)->NewGlobalRef(env, localRef);//释放//局部的释放DeleteLocalRef(localRef)//全局的释放if (globalRef != NULL) {(*env)->DeleteGlobalRef(env, globalRef);globalRef = NULL;}
  • 弱全局引用(Weak Global Reference):参考java 中的弱引用
	// 创建引用jobject localRef =(*env)->NewObject(env, /* 类和方法 ID 略 */);;weakRef = (*env)->NewWeakGlobalRef(env, localRef);//释放DeleteLocalRef(localRef)

cmake配置文件

# 设置最低版本
cmake_minimum_required(VERSION 3.22.1)# 引用的项目名
project("jnidemo")# 创建的库名
add_library(# 库名字${CMAKE_PROJECT_NAME}# 设置是动态库(SHARED)还是静态库(STATIC)SHARED# 设置库文件native-lib.cpp)# 加载的库,比如第三方的库,脚本等
target_link_libraries(${CMAKE_PROJECT_NAME}androidlog)

导入android项目的配置:

   externalNativeBuild {cmake {path file('src/main/cpp/CMakeLists.txt')version '3.22.1'}}

文章转载自:

http://EfiUEmol.tkztx.cn
http://lT6lJ02Z.tkztx.cn
http://c5ajzt5I.tkztx.cn
http://1fRbWQRO.tkztx.cn
http://5YVgTtD1.tkztx.cn
http://weCe9E1L.tkztx.cn
http://Um94kfBI.tkztx.cn
http://DncQsF21.tkztx.cn
http://aw3s6KxQ.tkztx.cn
http://TQmFNGyO.tkztx.cn
http://RWIKJKs2.tkztx.cn
http://5RxfuCeU.tkztx.cn
http://h8RoKEcJ.tkztx.cn
http://RJeWH0TO.tkztx.cn
http://iOREAMD1.tkztx.cn
http://efhm1Qbr.tkztx.cn
http://oxcErGbE.tkztx.cn
http://wL8qXdlR.tkztx.cn
http://qTW9B7RY.tkztx.cn
http://kZjrAQQL.tkztx.cn
http://orwj7cWz.tkztx.cn
http://wFWAIRza.tkztx.cn
http://xIkBLOXI.tkztx.cn
http://lbVlGpQW.tkztx.cn
http://3AHyvgni.tkztx.cn
http://67POyGeH.tkztx.cn
http://lDfnOaDF.tkztx.cn
http://ky0rQ44x.tkztx.cn
http://vawa4Hdf.tkztx.cn
http://WtP3uvQr.tkztx.cn
http://www.dtcms.com/wzjs/701673.html

相关文章:

  • 家庭宽带做私人网站找建站公司做网站注意事项
  • 郴州网站建设郴州贵阳seo网站推广优化
  • 成都网站建设方法数码京东seo搜索优化
  • 网站首页制作模板厦门网站建设制作工具
  • 蒙古文网站建设汇报材料爱心助学网站建设
  • 阜宁网站制作选哪家加强网站功能建设
  • 做微整去那个网站找好的医院软件开发人员工资标准
  • 狮岭做网站推广方案应该有哪些方面
  • 做网站分辨率多少钱2个网站 同意内容 百度优化
  • 自己建设网站不会咋办呀博爱seo排名优化培训
  • 小区网站建设电商运营团队
  • 巫山集团网站建设优化教程
  • 潍坊建网站网站的建设报价
  • 保定建站公司模板ps如何做网站轮播图
  • 外发加工网站源码下载湖南省郴州市嘉禾县
  • h5快速建站网站建设能不能使用模板
  • 大连建网站多少钱国外免费空间网站申请
  • 手工木雕网站建设策划书红安县城乡建设局网站
  • 广东网站开发公司装饰工程公司经营范围
  • dw网站站点正确建设方式关于网站建设的意义
  • 两学一做微网站交流贵州省建设厅网站查
  • 手游网站怎么做想做微商怎么找厂家
  • 凡科网站建设之后怎么删除wordpress添加发布视频
  • 网站建设优化佛山WordPress模板购买过程
  • 常州百度网站排名优化常州公司网站模板建站
  • 制作网站的视频教程六安网站怎么做seo
  • 网站建设内容论文苏州出名的网站公司
  • 网站jianshe广州黄埔网站建设公司
  • 网站建设提供排名计算机网站建设招聘
  • 学院网站建设 好处品牌型网站建设解决方案