当前位置: 首页 > 科技观察

HarmonyosNativeSDKC++(JNI)开发实践

时间:2023-03-14 19:25:46 科技观察

更多内容请访问:与华为官方共建的Harmonyos技术社区https://harmonyos.51cto.com什么是鸿蒙NativeSDKNativeSDK是一套能够使能的工具HarmonyOS应用中使用C和C++代码,并提供了很多平台库,NativeSDK可能不适合大多数编程初学者,他们只需要使用Java/JS代码和框架API来开发应用程序。但是,如果需要实现以下一个或多个目标,则NativeSDK可以派上用场:可以进一步增强设备性能以减少延迟或运行计算密集型应用程序,例如游戏和物理模拟。重用您自己或其他开发人员的C或C++库。HarmonyOS提供了一些与图形、图像、日志和媒体相关的NativeAPI。1鸿蒙NDK开发环境准备1.1开发工具DevEcostudio安装确认开发工具DevEcostudio已安装,版本需要支持NativeSDK。本文版本为DevEcostudio2.2.0.200。该工具可在鸿蒙官网下载。如果没有2.2版本,可以去hmxt.club下载1.2Setupandinstallation第一次安装NativeSDK(NDK),一般默认安装NDK。如果需要修改版本,点击左下角的Configure进入设置。如果项目已经打开,选择DevEcostudio的菜单File->Settings。2第一个HarmonyOS应用NDK示例2.1创建第一个HarmonyOsNativeC++工程2.2NativeC++工程文件分析2.2.1build.gradle鸿蒙app工程配置路径入口/build.gradle配置编译后的CPU对应的架构arm64-v8a配置C++项目编译的cmake文件src/main/cpp/CMakeLists.txt配置C++编译参数-指定C++版本-std=c++172.2.2CMakeList.txt(C++项目文件)路径入口/src/main/cpp/CMakeList.txtadd_library(helloSHAREDhello.cpp)输出为动态库指定c++源码文件target_link_libraries(hellolibhilog_ndk.z.so)setprojectdependentlibrary2.2.3ndkc++sourcecode(jni.h)pathentry/src/main/cpp/hello.cpp使用java调用引用jni.h对应的函数名与java进行交互JNIEnv*环境,jobjectobj){std::stringhello="HellofromJNIC++codes";intlen=hello.size();jcharres[len];for(inti=0;iNewString(res,len);}2.2.4ndkjava源文件名MainAbilitySlice.javaSystem.loadLibrary("hello");importc++动态库C++函数和java函数绑定假设java函数名是publicnativeStringstringFromJNI();那么java_namespace_classname_function=C语言函数,所以c++函数名是Java_com_example_myapplication_slice_MainAbilitySlice_stringFromJNI(JNIEnv*env,jobjectobj),如下参数对应Java线程环境和调用stringFromJNI函数的对象3NativeSDK(NDK)原生C++接口分析上一章创建项目后,本章分析C++可以调用哪些接口和C++程序3.1OfficialNativeAPI参考官方直接提供api参考,目前鸿蒙自带的接口支持的不多3.2NativeAPI支持标准库3.3鸿蒙原生SDK工具和库解析在DevEcostudio的菜单File->ProjectStructure中,可以看到项目引用的ndk的路径,可以设置修改t他版本的ndk。本文选用2.2.0.1版本的ndk。进入ndk目录可以看到:llvm目录下面是编译工具链,包括编译工具和C/C++库。进入llvm/bin后可以看到编译的工具是clang和clang++。sysroot是系统库和头文件路径。通过头文件和库文件可以看到OpenGLES3D渲染OpenSLES原声也支持,原生音频opensles已经测试可以正常调用,OpenGLES3D渲染没有调用测试,但是开源3D引擎已经成功通过鸿蒙ndk工具编译。NDK配置cmake说明JNI实现C++与java交互4JNI入门4.1什么是JNIJNI是指JavaNativeInterface。它定义了Java编译的字节码与本机代码(用C/C++编写)交互的方式。JNI独立于供应商,支持从动态共享库加载代码。4.2JNI开发原则尽可能减少跨JNI层的资源传输次数避免JAVA与C++之间的异步通信尽可能减少需要联系JNI或被JNI联系的线程数保持接口代码小4.3JavaVM和JNIEnvJavaVMJava语言的执行环境是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.4jclass、jmethodID、jfieldID分别对应java中的类、成员函数和成员变量。传递给本地方法的每个参数,以及JNI函数返回的几乎每个对象,都是“本地引用”。这意味着本地引用在当前线程中的当前本机方法的持续时间内有效。本地方法返回后引用无效,即使对象本身继续存在。获取非本地引用的唯一方法是通过NewGlobalRef和NewWeakGlobalRef函数。JNICMakeninjaNDKc++java的关系就结束了。更多jni接口参数可以直接查看java手册。更多内容可以在51cto学堂观看课程《鸿蒙Native SDK JNI C++开发入门和实战-示例扩展支持lua脚本》,也可以关注我后面发的文章。更多信息请访问:Harmonyos.51cto.com,与华为官方合作打造的鸿蒙技术社区