zl程序教程

您现在的位置是:首页 >  APP

当前栏目

鸿蒙应用Native SDK C++ (JNI)开发实战

2023-04-18 15:44:59 时间

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

什么是鸿蒙Native SDK

  • Native SDK是一套工具,使您能够在 HarmonyOS 应用中使用 C 和 C++ 代码,并提供众多平台库,Native SDK 可能不适合大多数编程初学者,这些初学者只需使用 Java /JS代码和框架 API 开发应用。然而,如果需要实现以下一个或多个目标,那么 Native SDK 就能派上用场:
  • 可以进一步提升设备性能,以降低延迟或运行游戏、物理模拟等计算密集型应用。
  • 重复使用您自己或其他开发者的 C 或 C++ 库。

HarmonyOS提供了一些图形图像、日志、媒体等相关的Native API。

1 鸿蒙NDK开发环境准备

1.1 开发工具DevEco studio安装

  • 确认安装好开发工具DevEco studio,版本需要支持Native SDK的
  • 本文章的版本是 DevEco studio 2.2.0.200
  • 工具到鸿蒙官网下载,如果已经没有2.2版本可以到hmxt.club下载

1.2 设置安装Native SDK(NDK)

第一次安装,正常默认安装了NDK,如需要修改版本,点击左下角Configure 进入设置。

鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区

如果已经打开项目则选中DevEco studio的菜单File->Settings。

鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区

2 第一个鸿蒙应用NDK示例

2.1 创建第一个HamonyOs Native C++项目

鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区

2.2 Native C++项目的文件分析

2.2.1 build.gradle 鸿蒙app项目配置

  • 路径entry/build.gradle
  • 配置编译的CPU对应的架构 arm64-v8a
  • 配置C++项目编译用的cmake文件 src/main/cpp/CMakeLists.txt
  • 配置C++ 编译参数-指定C++ 版本 -std=c++17
鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区

2.2.2 CMakeList.txt (C++项目文件)

  • 路径 entry/src/main/cpp/CMakeList.txt
  • add_library(hello SHARED hello.cpp)
  • 输出为动态库 指定c++源码文件
  • target_link_libraries(hello libhilog_ndk.z.so)
  • 设定项目依赖的库
鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区

2.2.3 ndk c++源码(jni.h)

  • 路径 entry/src/main/cpp/hello.cpp
  • 通过函数名称对应java调用
  • 引用jni.h与java交互
  1. #include <jni.h> 
  2. #include <string> 
  3. #include <Hilog/log.h> 
  4. extern "C" 
  5. JNIEXPORT jstring JNICALL 
  6. Java_com_example_myapplication_slice_MainAbilitySlice_stringFromJNI(JNIEnv* env, jobject  obj) { 
  7.     std::string hello = "Hello from JNI C++ codes"
  8.     int len = hello.size(); 
  9.     jchar res[len]; 
  10.     for (int i = 0; i < len; i++) { 
  11.         res[i] = (jchar)hello[i]; 
  12.     } 
  13.     return env->NewString(res, len); 

2.2.4 ndk java源码

  • 文件名 MainAbilitySlice.java
  • System.loadLibrary(“hello”);
  • 导入c++动态库
  • C++函数与java函数绑定

假定java函数名为 public native String stringFromJNI(); 那 java_命名空间_类名_函数 = C语言函数 ,所以c++函数名为Java_com_example_myapplication_slice_MainAbilitySlice_stringFromJNI(JNIEnv* env, jobject obj),后面的参数对应java的线程环境和调用stringFromJNI函数的对象。

鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区

3 Native SDK (NDK)原生的C++接口分析

  • 在上一章创建项目后,本章分析下c++能够调用哪些接口、c++程序的编译流程、库和编译工具所在路径。

3.1 官方Native API参考

官方直接提供了api的参考,目前鸿蒙自身的接口支持得还不多。

鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区

3.2 Native API支持得标准库

鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区

3.3 分析鸿蒙native SDK 工具和库

在DevEco studio的菜单File->Project Structure进入可以看到,项目引用的ndk的路径,并且可以设置修改ndk的版本,本文选择了2.2.0.1版本的ndk。

鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区

进入ndk目录可以看到:

鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区

其中llvm目录下是编译工具链,包含编译工具和C/C++ 库,进入llvm/bin后可以看到编译的工具是clang 和clang++。

鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区

sysroot是系统库和头文件路径。

鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区
鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区

通过头文件和库文件可以看到OpenGLES 三维渲染 OpenSLES 原始音频 也是支持的,原生音频opensles已测可以正常调用,OpenGLES 三维渲染没有调用测试,但是通过鸿蒙ndk工具已经成功编译开源的三维引擎。

NDK配置 cmake说明

JNI实现C++与java交互

4 JNI入门

4.1 什么是JNI

  • JNI 是指 Java 原生接口。它定义了Java编译的字节码与原生代码(使用 C/C++ 编写)互动的方式。JNI 不依赖于供应商,支持从动态共享库加载代码。

4.2 JNI开发原则

  • 尽可能减少跨 JNI 层传递资源的次数
  • 尽可能避免JAVA与C++异步通信
  • 尽可能减少需要接触 JNI 或被 JNI 接触的线程数
  • 将接口代码保存在少量易于识别的 C++ 和 Java 源位置,以便将来进行重构

4.3 JavaVM 和 JNIEnv

JavaVM

  • Java语言的执行环境是Java虚拟机(JVM),每个JVM虚拟机都在本地环境中有一个JavaVM结构体,JavaVM是Java虚拟机在JNI层的代表,JNI全局仅仅有一个JavaVM结构中封装了一些函数指针(或叫函数表结构),JavaVM中封装的这些函数指针主要是对JVM操作接口。

JNIEnv

  • 每个线程对应一个JNIEnv结构
  • JNIEnv 提供了大部分 JNI 函数。原生函数第一个参数都是JNIEnv
  • 您无法在线程之间共享 JNIEnv
  • 可以使用 AttachCurrentThread() 或 AttachCurrentThreadAsDaemon() 函数附加通过 pthread_create() 或 std::thread 启动的线程。
  • 在附加之前,线程不包含任何 JNIEnv,也无法调用 JNI
  • JNI 附加的线程在退出之前必须调用 DetachCurrentThread()

4.4 jclass、jmethodID 和 jfieldID

  • 分别对应java中的类、成员函数和成员变量。
  • 传递给原生方法的每个参数,以及 JNI函数返回的几乎每个对象都属于“局部引用”。这意味着,局部引用在当前线程中的当前原生方法运行期间有效。在原生方法返回后,即使对象本身继续存在,该引用也无效。
  • 获取非局部引用的唯一方法是通过 NewGlobalRef 和 NewWeakGlobalRef 函数。

JNI CMake ninja NDK c++ java的关系

鸿蒙应用Native SDK C++ (JNI)开发实战-鸿蒙HarmonyOS技术社区

结束

更多jni接口参数可以直接查看java的手册

更多内容可以观看51cto学堂上的课程《鸿蒙Native SDK JNI C++开发入门和实战-示例扩展支持lua脚本》,也可以关注我后发发的文章。

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com