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

帮我们公司做网站百度在线客服中心

帮我们公司做网站,百度在线客服中心,网站建设域名提前买吗,阿里云学生服务器购买1. 引言 在Android开发中,NDK(Native Development Kit)允许开发者使用C/C编写高性能代码,并通过JNI(Java Native Interface)与Java/Kotlin层交互。本文将深入探讨: NDK开发的本质JNI中基本类型…

1. 引言

在Android开发中,NDK(Native Development Kit)允许开发者使用C/C++编写高性能代码,并通过JNI(Java Native Interface)与Java/Kotlin层交互。本文将深入探讨:

  1. NDK开发的本质
  2. JNI中基本类型与对象类型的处理差异
  3. 如何调用第三方C库

通过实际代码示例,帮助开发者掌握NDK的核心机制。


2. NDK开发的本质

NDK的核心作用是:

  • 编译C/C++代码:生成Android可用的动态库(.so)或静态库(.a)。
  • 提供JNI桥梁:实现Java/Kotlin与原生代码的交互。

为什么需要NDK?

  • 性能优化:计算密集型任务(如音视频处理)用C/C++更高效。
  • 复用现有库:直接调用成熟的C/C++库(如OpenCV、FFmpeg)。
  • 底层操作:访问硬件或系统级API(如POSIX线程)。

3. JNI的数据类型处理规则

在JNI中,**基本数据类型(如 intdouble 等)对象类型(如 StringObject 等)**的处理方式不同,这是由Java和JNI的设计机制决定的。下面详细解释为什么 intString 的返回方式不同:

3.1 基本数据类型(Primitive Types)可以直接返回

在JNI中,Java的基本数据类型(intdoubleboolean 等)在C/C++层有对应的 “直接映射” 类型(如 jintjdoublejboolean),它们本质上就是C/C++的基本类型(intdoubleunsigned char 等),因此可以直接返回,不需要额外转换。

示例:int 加法

JNIEXPORT jint JNICALL
Java_com_example_MainActivity_add(JNIEnv *env, jobject obj, jint a, jint b) {return a + b; // 直接返回 jint(本质是 int)
}
  • jint 就是 int,所以可以直接返回,JVM会自动处理。

3.2 对象类型(如 String)必须通过 JNIEnv 创建

Java的 String对象类型,而C/C++中的字符串(char*std::string)是 原生数据,它们不能直接互转。因此,必须通过 JNIEnv 提供的函数来创建 Java 字符串对象。

示例:返回 String

JNIEXPORT jstring JNICALL
Java_com_example_MainActivity_getString(JNIEnv *env, jobject obj) {std::string cppStr = "Hello JNI";return env->NewStringUTF(cppStr.c_str()); // 必须用 JNIEnv 创建 Java String
}
  • jstring 是 Java 层的 String 对象,不能直接用 return "Hello",必须调用 NewStringUTF() 进行转换。

3.3 为什么 int 可以直接返回,而 String 不行?

数据类型C/C++ 类型JNI 类型是否需要 JNIEnv 转换原因
intintjint❌ 不需要jint 就是 int,直接兼容
doubledoublejdouble❌ 不需要jdouble 就是 double
Stringchar*jstring✅ 需要Java 的 String 是对象,必须通过 JNIEnv 创建
  • 基本数据类型intfloatboolean 等)在 JNI 中只是简单的类型别名,可以直接返回。
  • 对象类型StringObjectArray 等)必须通过 JNIEnv 提供的 API 进行转换。

3.4 进阶:如果返回自定义对象怎么办?

如果要从 JNI 返回一个 Java 自定义对象(如 Person),也必须通过 JNIEnv 创建对象并设置字段:

示例:返回 Java 对象

JNIEXPORT jobject JNICALL
Java_com_example_MainActivity_getPerson(JNIEnv *env, jobject obj) {// 1. 找到 Java 的 Person 类jclass personClass = env->FindClass("com/example/Person");// 2. 获取构造方法 IDjmethodID constructor = env->GetMethodID(personClass, "<init>", "(ILjava/lang/String;)V");// 3. 创建 Java 字符串jstring name = env->NewStringUTF("Alice");// 4. 创建 Person 对象jobject person = env->NewObject(personClass, constructor, 25, name);return person;
}
  • jobject 必须通过 JNIEnv 创建,不能直接返回 C/C++ 结构体。

3.5 进阶:JNI 如何处理 Kotlin 的 “基本类型”?

在 Kotlin 中,虽然基本类型(如 IntDouble 等)在语言层面表现为对象类型,但在 JVM 字节码层面,它们仍然会被优化为原始类型(primitive types),除非被声明为可空类型(Int?)或用于泛型场景。这种设计对 JNI 交互有直接影响,以下是详细解释:

Kotlin 为了保持语言一致性,将所有类型(包括数字、布尔值)都表现为对象类型。但在编译后的字节码中:

  • 非空基本类型(如 IntDouble → 编译为 JVM 原始类型(intdouble

  • 可空基本类型(如 Int? → 编译为 Java 包装类(IntegerDouble

  • 泛型中使用的基本类型(如 List<Int> → 编译为包装类(因 JVM 类型擦除)

  • Kotlin 代码

    external fun safeDivide(a: Int, b: Int?): Int?  // 可空 Int
    
  • JNI 映射

    • Kotlin 的 Int? → JNI 的 jobject(即 java.lang.Integer
    • 必须通过 JNIEnv 方法操作:
      JNIEXPORT jobject JNICALL
      Java_com_example_MainActivity_safeDivide(JNIEnv *env, jobject obj, jint a, jobject bObj) {if (bObj == nullptr) {return nullptr; // 返回 Kotlin 的 null}// 从 Integer 对象中提取 int 值jclass integerClass = env->FindClass("java/lang/Integer");jmethodID intValueMethod = env->GetMethodID(integerClass, "intValue", "()I");jint b = env->CallIntMethod(bObj, intValueMethod);if (b == 0) {return nullptr; // 除零返回 null}// 将结果包装为 Integer 对象jmethodID valueOfMethod = env->GetStaticMethodID(integerClass, "valueOf", "(I)Ljava/lang/Integer;");return env->CallStaticObjectMethod(integerClass, valueOfMethod, a / b);
      }
      

为什么 Kotlin 非空基本类型在 JNI 中仍按原始类型处理?

  • 性能优化:JVM 会对基本类型进行特殊处理,避免对象开销。
  • 字节码兼容性:Kotlin 最终编译为 JVM 字节码,非空基本类型会退化为原始类型。
  • JNI 规范:JNI 的设计基于 JVM 底层机制,直接支持原始类型交互。

如果不需要可空性,尽量用 Int 而非 Int?,减少 JNI 的复杂度。

// 推荐:JNI 直接处理 jint
external fun add(a: Int, b: Int): Int// 避免:需处理 Integer 对象
external fun addNullable(a: Int?, b: Int?): Int?

如果必须用 Int?,需在 JNI 中调用 Integer.intValue()Integer.valueOf()


4. 调用第三方C库的完整流程

步骤1:集成C库

  • 将头文件(.h)和库文件(.so/.a)放入项目。
  • 配置CMakeLists.txt链接库:
    add_library(math STATIC IMPORTED)
    set_target_properties(math PROPERTIES IMPORTED_LOCATION libmath.a)
    target_link_libraries(native-lib math)
    

步骤2:编写JNI包装函数

// 调用第三方库的add()函数
JNIEXPORT jint JNICALL
Java_com_example_MainActivity_addFromCLib(JNIEnv *env, jobject obj, jint a, jint b) {return add(a, b); // 直接调用C函数
}

步骤3:Java/Kotlin调用

init {System.loadLibrary("native-lib")
}
val result = addFromCLib(3, 5) // 调用第三方库

5. 总结

  1. NDK本质:是Android与C/C++交互的桥梁,核心是JNI。
  2. 基本类型:直接映射(如jintint),无需转换。
  3. 对象类型:必须通过JNIEnv转换(如NewStringUTF)。
  4. 调用第三方库:需编写JNI包装函数,处理数据类型差异。

掌握这些规则后,你可以安全地在Android中集成任何C/C++库,并高效地跨语言交互。

进一步学习

  • Android NDK官方文档
  • JNI规范(Oracle文档)
http://www.dtcms.com/wzjs/70118.html

相关文章:

  • dede模板用图片多的网站不行创建自己的网页
  • 企业网站建设运营武威网站seo
  • 如何做家教网刘连康seo培训哪家强
  • 网站建设相关关键词谷歌浏览器下载安装
  • 靓号网站开发网络营销八大目标是什么
  • 南昌中企动力做的网站怎么样人工智能培训班
  • 公司工商查询宁波seo整体优化
  • 有什么网站可以做微信宁波seo关键词优化制作
  • 制作个人网页作品谷歌seo推广招聘
  • 可靠手机网站建设百度搜索官方网站
  • 公司网站建设费计入哪个科目足球积分排行榜最新
  • 扬州公司做网站公司哪家好西安关键词优化服务
  • 网站建设销售信淘宝关键词排名查询
  • 正规的佛山网站建设价格软文推广营销
  • 网站建设flash设计如何制作网页教程
  • 动漫做暧视频在线观看网站宁德市地图
  • 网站做seo优化有什么优势域名访问网站
  • 阅读网站策划书域名注册信息怎么查
  • 网站开发软件怎么做杯子软文营销300字
  • 外贸网站建站口碑营销案例简短
  • 网站开发 证书友情连接出售
  • 亚洲网站建设中会计培训班推荐
  • 男女怎样做那个视频网站2024年最新时事新闻
  • 网站建设项目实施计划书网页制作基础教程
  • 深圳制作网站开发费用三只松鼠搜索引擎推广
  • 哪个网站可以做照片分享百度知道免费提问
  • 旅游网站开发的意义是什么商家怎么入驻百度
  • 大连网站推广合肥今天的最新消息
  • 青岛做网站好的公司衡水seo排名
  • 外贸公司网站多少钱百度地图导航手机版免费下载