GHOST系统之家 - Windows系统光盘下载网站!
当前位置:GHOST系统之家>系统教程 > 跟着小白一起学鸿蒙—HAP应用调用SO库方法-鸿蒙hap开发

跟着小白一起学鸿蒙—HAP应用调用SO库方法-鸿蒙hap开发

来源:Ghost系统之家浏览:时间:2023-08-27 09:24:50

跟着小白一起学鸿蒙—HAP应用调用SO库方法

作者:王石 2022-12-09 15:34:38系统 OpenHarmony 在ETS的框架接口里OpenHarmony提供了一种更方便快捷的方式就是利用XComponent组件和NDK的方式快速进行业务层逻辑实现和动态库(so)的调用。

​​想了解更多关于开源的内容,请访问:​​

​​51CTO开源基础软件社区​​

​​https://ost.51cto.com​​

概述

在《[#跟着小白一起学鸿蒙# 七] 写个NAPI子系统》的文章里我们熟悉了如何用NAPI框架实现一个HAP应用的业务接口,但是这只是OpenHarmony提供的一种实现方式。在ETS的框架接口里OpenHarmony提供了一种更方便快捷的方式就是利用XComponent组件和NDK的方式快速进行业务层逻辑实现和动态库(so)的调用。

XComponent组件

参考文档链接:https://developer.harmonyos.com/cn/docs/documentation/doc-references/ts-basic-components-xcomponent-0000001333800561

接口

XComponent(value: {id: string, type: string, libraryname?: string, controller?: XComponentController})

参数:

参数名

参数类型

必填

描述

id

string

组件的唯一标识,支持最大的字符串长度128。

type

string

用于指定XComponent组件类型,可选值为: -surface:组件内容单独送显,直接合成到屏幕。 -component:组件内容与其他组件合成后统一送显。

libraryname

string

应用Native层编译输出动态库名称。

controller

​​XComponentcontroller​​

给组件绑定一个控制器,通过控制器调用组件方法。

事件

插件加载完毕后的回调事件(onLoad):onLoad(callback: (event?: object) => void )

参数:

参数名

参数类型

必填

描述

event

object

获取XComponent实例对象的context,context上挂载的方法由开发者在c++层定义。

插件卸载完毕后的回调(onDestroy):onDestroy(event: () => void )。

获取C++实例对象接口。

getXComponentContext()。

返回值:

类型

描述

Object

获取XComponent实例对象的context,context包含的具体接口方法由开发者自定义。

样例开发

应用层开发:

和一般的HAP应用开发一样基于ets的页面开发,代码如下:

import nativerender from "libnativerender.so";import { ContextType } from "../common/Constants"const nativePageLifecycle = nativerender.getContext(ContextType.JSPAGE_LIFECYCLE);@Entry@Componentstruct Index {private context = null;aboutToAppear() {console.log('[LIFECYCLE-Index] aboutToAppear');nativePageLifecycle.aboutToAppear();}aboutToDisappear() {console.log('[LIFECYCLE-Index] aboutToDisappear');nativePageLifecycle.aboutToDisappear();}onPageShow() {console.log('[LIFECYCLE-Page] onPageShow');nativePageLifecycle.onPageShow();}onPageHide() {console.log('[LIFECYCLE-Page] onPageHide');nativePageLifecycle.onPageHide();}build() {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {Button('ChangeColor').onClick(() => {if (this.context) {this.context.changeColor();}}).width(200).height(80)Button('ChangeShape').onClick(() => {if (this.context) {this.context.changeShape();}}).width(200).height(80)XComponent({ id: 'xcomponentId', type: 'texture', libraryname: 'nativerender'}).onLoad((context) => {this.context = context;}).onDestroy(() =>{})}.width('100%').height('100%')}}

CPP层开发:

编写CMakeList:

# the minimum version of CMake.cmake_minimum_required(VERSION 3.4.1)project(XComponent)set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})add_definitions(-DOHOS_PLATFORM)include_directories(${NATIVERENDER_ROOT_PATH}${NATIVERENDER_ROOT_PATH}/common${NATIVERENDER_ROOT_PATH}/napi${NATIVERENDER_ROOT_PATH}/render)add_library(nativerender SHAREDrender/egl_core.cpprender/plugin_render.cppplugin_manager.cppnapi/napi_init.cpp)find_library( # Sets the name of the path variable.EGL-lib# Specifies the name of the NDK library that# you want CMake to locate.EGL )find_library( # Sets the name of the path variable.GLES-lib# Specifies the name of the NDK library that# you want CMake to locate.GLESv3 )find_library( # Sets the name of the path variable.hilog-lib# Specifies the name of the NDK library that# you want CMake to locate.hilog_ndk.z )find_library( # Sets the name of the path variable.libace-lib# Specifies the name of the NDK library that# you want CMake to locate.ace_ndk.z )find_library( # Sets the name of the path variable.libnapi-lib# Specifies the name of the NDK library that# you want CMake to locate.ace_napi.z )find_library( # Sets the name of the path variable.libuv-lib# Specifies the name of the NDK library that# you want CMake to locate.uv )target_link_libraries(nativerender PUBLIC ${EGL-lib} ${GLES-lib} ${hilog-lib} ${libace-lib} ${libnapi-lib} ${libuv-lib} libc++.

NAPI接口:

#include "plugin_common.h"#include "plugin_manager.h"/* * function for module exports */static napi_value Init(napi_env env, napi_value exports){LOGE("Init");napi_property_descriptor desc[] ={DECLARE_NAPI_FUNCTION("getContext", PluginManager::GetContext),};NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));bool ret = PluginManager::GetInstance()->Export(env, exports);if (!ret) {LOGE("Init failed");}return exports;}/* * Napi Module define */static napi_module nativerenderModule = {.nm_version = 1,.nm_flags = 0,.nm_filename = nullptr,.nm_register_func = Init,.nm_modname = "nativerender",.nm_priv = ((void*)0),.reserved = { 0 },};/* * Module register function */extern "C" __attribute__((constructor)) void RegisterModule(void){napi_module_register(&nativerenderModule);}

XComponent框架适配:

#include#include#include#include#include "plugin_manager.h"#include "plugin_common.h"enum ContextType {APP_LIFECYCLE = 0,JS_PAGE_LIFECYCLE,};PluginManager PluginManager::manager_;napi_value PluginManager::GetContext(napi_env env, napi_callback_info info){napi_status status;napi_value exports;size_t argc = 1;napi_value args[1];NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));if (argc != 1) {napi_throw_type_error(env, NULL, "Wrong number of arguments");return nullptr;}napi_valuetype valuetype;status = napi_typeof(env, args[0], &valuetype);if (status != napi_ok) {return nullptr;}if (valuetype != napi_number) {napi_throw_type_error(env, NULL, "Wrong arguments");return nullptr;}int64_t value;NAPI_CALL(env, napi_get_value_int64(env, args[0], &value));NAPI_CALL(env, napi_create_object(env, &exports));switch (value) {case APP_LIFECYCLE:{/**** AppInit 对应 app.ets中的应用生命周期 onCreate, onShow, onHide, onDestroy ******/LOGD("GetContext APP_LIFECYCLE");/**** Register App Lifecycle******/napi_property_descriptor desc[] = {DECLARE_NAPI_FUNCTION("onCreate", PluginManager::NapiOnCreate),DECLARE_NAPI_FUNCTION("onShow", PluginManager::NapiOnShow),DECLARE_NAPI_FUNCTION("onHide", PluginManager::NapiOnHide),DECLARE_NAPI_FUNCTION("onDestroy", PluginManager::NapiOnDestroy),};NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));}break;case JS_PAGE_LIFECYCLE:{/****************声明式开发范式 JS Page 生命周期注册 ****************************/LOGD("GetContext JS_PAGE_LIFECYCLE");napi_property_descriptor desc[] = {DECLARE_NAPI_FUNCTION("onPageShow", PluginManager::NapiOnPageShow),DECLARE_NAPI_FUNCTION("onPageHide", PluginManager::NapiOnPageHide),};NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));}break;default:LOGE("unknown type");}return exports;}bool PluginManager::Export(napi_env env, napi_value exports){napi_status status;napi_value exportInstance = nullptr;OH_NativeXComponent *nativeXComponent = nullptr;int32_t ret;char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { };uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;status = napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance);if (status != napi_ok) {return false;}status = napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent));if (status != napi_ok) {return false;}ret = OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize);if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {return false;}std::string id(idStr);auto context = PluginManager::GetInstance();if (context) {context->SetNativeXComponent(id, nativeXComponent);auto render = context->GetRender(id);render->SetNativeXComponent(nativeXComponent);render->Export(env, exports);return true;}return false;}void PluginManager::SetNativeXComponent(std::string& id, OH_NativeXComponent* nativeXComponent){if (nativeXComponentMap_.find(id) == nativeXComponentMap_.end()) {nativeXComponentMap_[id] = nativeXComponent;} else {if (nativeXComponentMap_[id] != nativeXComponent) {nativeXComponentMap_[id] = nativeXComponent;}}}OH_NativeXComponent* PluginManager::GetNativeXComponent(std::string& id){if (nativeXComponentMap_.find(id) == nativeXComponentMap_.end()) {return nullptr;} else {return nativeXComponentMap_[id];}}PluginRender* PluginManager::GetRender(std::string& id){if (pluginRenderMap_.find(id) == pluginRenderMap_.end()) {PluginRender* instance = PluginRender::GetInstance(id);pluginRenderMap_[id] = instance;return instance;} else {return pluginRenderMap_[id];}}void PluginManager::MainOnMessage(const uv_async_t* req){LOGD("MainOnMessage Triggered");}napi_value PluginManager::NapiOnCreate(napi_env env, napi_callback_info info){LOGD("PluginManager::NapiOnCreate");uv_loop_t* loop = nullptr;uv_check_t* check = new uv_check_t;NAPI_CALL(env, napi_get_uv_event_loop(env, &loop));PluginManager::GetInstance()->OnCreateNative(env, loop);return nullptr;}napi_value PluginManager::NapiOnShow(napi_env env, napi_callback_info info){PluginManager::GetInstance()->OnShowNative();return nullptr;}napi_value PluginManager::NapiOnHide(napi_env env, napi_callback_info info){PluginManager::GetInstance()->OnHideNative();return nullptr;}napi_value PluginManager::NapiOnDestroy(napi_env env, napi_callback_info info){PluginManager::GetInstance()->OnDestroyNative();return nullptr;}void PluginManager::OnCreateNative(napi_env env, uv_loop_t* loop){mainEnv_ = env;mainLoop_ = loop;if (mainLoop_) {uv_async_init(mainLoop_, &mainOnMessageSignal_, reinterpret_cast(PluginManager::MainOnMessage));}}void PluginManager::OnShowNative(){LOGD("PluginManager::OnShowNative");}void PluginManager::OnHideNative(){LOGD("PluginManager::OnHideNative");}void PluginManager::OnDestroyNative(){LOGD("PluginManager::OnDestroyNative");}napi_value PluginManager::NapiOnPageShow(napi_env env, napi_callback_info info){LOGD("PluginManager::NapiOnPageShow");return nullptr;}napi_value PluginManager::NapiOnPageHide(napi_env env, napi_callback_info info){LOGD("PluginManager::NapiOnPageHide");return nullptr;}void PluginManager::OnPageShowNative(){LOGD("PluginManager::OnPageShowNative");}void PluginManager::OnPageHideNative(){LOGD("PluginManager::OnPageHideNative");}

界面渲染适配:

#include#include "plugin_render.h"#include "plugin_common.h"#include "plugin_manager.h"#ifdef __cplusplusextern "C" {#endifstd::unordered_map PluginRender::instance_;OH_NativeXComponent_Callback PluginRender::callback_;void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window){LOGD("OnSurfaceCreatedCB");int32_t ret;char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {return;}std::string id(idStr);auto render = PluginRender::GetInstance(id);render->OnSurfaceCreated(component, window);}void OnSurfaceChangedCB(OH_NativeXComponent* component, void* window){int32_t ret;char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {return;}std::string id(idStr);auto render = PluginRender::GetInstance(id);render->OnSurfaceChanged(component, window);}void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window){int32_t ret;char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {return;}std::string id(idStr);auto render = PluginRender::GetInstance(id);render->OnSurfaceDestroyed(component, window);}void DispatchTouchEventCB(OH_NativeXComponent* component, void* window){LOGD("DispatchTouchEventCB");int32_t ret;char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {return;}std::string id(idStr);auto render = PluginRender::GetInstance(id);render->DispatchTouchEvent(component, window);}PluginRender::PluginRender(std::string& id) : id_(id), component_(nullptr){eglCore_ = new EGLCore(id);auto renderCallback = PluginRender::GetNXComponentCallback();renderCallback->OnSurfaceCreated = OnSurfaceCreatedCB;renderCallback->OnSurfaceChanged = OnSurfaceChangedCB;renderCallback->OnSurfaceDestroyed = OnSurfaceDestroyedCB;renderCallback->DispatchTouchEvent = DispatchTouchEventCB;}PluginRender* PluginRender::GetInstance(std::string& id){if (instance_.find(id) == instance_.end()) {PluginRender*instance = new PluginRender(id);instance_[id] = instance;return instance;} else {return instance_[id];}}OH_NativeXComponent_Callback* PluginRender::GetNXComponentCallback(){return &PluginRender::callback_;}void PluginRender::SetNativeXComponent(OH_NativeXComponent* component){component_ = component;OH_NativeXComponent_RegisterCallback(component_, &PluginRender::callback_);}void PluginRender::OnSurfaceCreated(OH_NativeXComponent* component, void* window){LOGD("PluginRender::OnSurfaceCreated");int32_t ret=OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {eglCore_->GLContextInit(window, width_, height_);}}void PluginRender::OnSurfaceChanged(OH_NativeXComponent* component, void* window){}void PluginRender::OnSurfaceDestroyed(OH_NativeXComponent* component, void* window){}void PluginRender::DispatchTouchEvent(OH_NativeXComponent* component, void* window){int32_t ret = OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent_);if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {LOGD("Touch Info : x = %{public}f, y = %{public}f screenx = %{public}f, screeny = %{public}f", touchEvent_.x, touchEvent_.y, touchEvent_.screenX, touchEvent_.screenY);for (int i=0;i(&nativeXComponent));if (status != napi_ok) {return nullptr;}ret = OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize);if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {return nullptr;}std::string id(idStr);PluginRender* instance = PluginRender::GetInstance(id);if (instance) {instance->eglCore_->ChangeShape();}return nullptr;}napi_value PluginRender::NapiDrawTriangle(napi_env env, napi_callback_info info){LOGD("NapiDrawTriangle");napi_value exportInstance;napi_value thisArg;napi_status status;OH_NativeXComponent *nativeXComponent = nullptr;int32_t ret;char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;// napi_value thisArg;NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &thisArg, NULL));status = napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance);if (status != napi_ok) {return nullptr;};status = napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent));if (status != napi_ok) {return nullptr;}ret = OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize);if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {return nullptr;}std::string id(idStr);PluginRender* instance = PluginRender::GetInstance(id);if (instance) {instance->eglCore_->DrawTriangle();}return nullptr;}napi_value PluginRender::NapiChangeColor(napi_env env, napi_callback_info info){LOGD("NapiChangeColor");napi_value exportInstance;napi_value thisArg;napi_status status;OH_NativeXComponent *nativeXComponent = nullptr;int32_t ret;char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;// napi_value thisArg;NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &thisArg, NULL));status = napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance);if (status != napi_ok) {return nullptr;}status = napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent));if (status != napi_ok) {return nullptr;}ret = OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize);if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {return nullptr;}std::string id(idStr);PluginRender* instance = PluginRender::GetInstance(id);if (instance) {instance->eglCore_->ChangeColor();}return nullptr;}#ifdef __cplusplus}#endif

业务逻辑适配:

#include "egl_core.h"#include "plugin_common.h"#include "plugin_render.h"#include #includeEGLConfig getConfig(int version, EGLDisplay eglDisplay) {int attribList[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT,EGL_RED_SIZE, 8,EGL_GREEN_SIZE, 8,EGL_BLUE_SIZE, 8,EGL_ALPHA_SIZE, 8,EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,EGL_NONE};EGLConfig configs = NULL;int configsNum;if (!eglChooseConfig(eglDisplay, attribList, &configs, 1, &configsNum)) {LOGE("eglChooseConfig ERROR");return NULL;}return configs;}char vertexShader[] ="#version 300 es\n""layout(location = 0) in vec4 a_position;\n""layout(location = 1) in vec4 a_color;\n""out vec4 v_color;\n""void main()\n""{\n"" gl_Position = a_position;\n"" v_color = a_color;\n""}\n";char fragmentShader[] ="#version 300 es\n""precision mediump float;\n""in vec4 v_color;\n""out vec4 fragColor;\n""void main()\n""{\n"" fragColor = v_color;\n""}\n";void EGLCore::GLContextInit(void* window, int w, int h){LOGD("EGLCore::GLContextInit window = %{public}p, w = %{public}d, h = %{public}d.", window, w, h);width_ = w;height_ = h;mEglWindow = static_cast(window);// 1. create sharedcontextmEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);if (mEGLDisplay == EGL_NO_DISPLAY) {LOGE("EGLCore::unable to get EGL display.");return;}EGLint eglMajVers, eglMinVers;if (!eglInitialize(mEGLDisplay, &eglMajVers, &eglMinVers)) {mEGLDisplay = EGL_NO_DISPLAY;LOGE("EGLCore::unable to initialize display");return;}mEGLConfig = getConfig(3, mEGLDisplay);if (mEGLConfig == nullptr) {LOGE("EGLCore::GLContextInit config ERROR");return;}// 2. Create EGL Surface from Native WindowEGLint winAttribs[] = {EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR, EGL_NONE};if (mEglWindow) {mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mEglWindow, winAttribs);if (mEGLSurface == nullptr) {LOGE("EGLCore::eglCreateContext eglSurface is null");return;}}// 3. Create EGLContext fromint attrib3_list[] = {EGL_CONTEXT_CLIENT_VERSION, 2,EGL_NONE};mEGLContext = eglCreateContext(mEGLDisplay, mEGLConfig, mSharedEGLContext, attrib3_list);if (!eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {LOGE("EGLCore::eglMakeCurrent error = %{public}d", eglGetError());}mProgramHandle = CreateProgram(vertexShader, fragmentShader);if (!mProgramHandle) {LOGE("EGLCore::Could not create CreateProgram");return;}DrawTriangle();}void EGLCore::DrawTriangle(){GLfloat color[] = {0.5f, 0.6f, 0.3f, 1.0f};const GLfloat triangleVertices[] = {0.0f, 1.0f,-1.0f, -1.0f,1.0f, -1.0f};glViewport(0, 0, width_, height_);glClearColor(0.0, 0.0, 0.0, 1.0);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(mProgramHandle);GLint positionHandle = glGetAttribLocation(mProgramHandle, "a_position");glVertexAttribPointer(positionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);glEnableVertexAttribArray(positionHandle);glVertexAttrib4fv(1, color);glDrawArrays(GL_TRIANGLES, 0, 3);glDisableVertexAttribArray(positionHandle);glFlush();glFinish();eglSwapBuffers(mEGLDisplay, mEGLSurface);}void EGLCore::ChangeShape(){if (!eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {LOGE("EGLCore::eglMakeCurrent error = %{public}d", eglGetError());}GLfloat color[] = {0.7f, 0.2f, 0.2f, 1.0f};const GLfloat triangleVertices[] = {-1.0f, 1.0f,-1.0f, -1.0f,1.0f, 0.0f};glViewport(0, 0, width_, height_);glClearColor(0.0, 0.0, 0.0, 1.0);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(mProgramHandle);GLint positionHandle = glGetAttribLocation(mProgramHandle, "a_position");glVertexAttribPointer(positionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);glEnableVertexAttribArray(positionHandle);glVertexAttrib4fv(1, color);glDrawArrays(GL_TRIANGLES, 0, 3);glDisableVertexAttribArray(positionHandle);Update();}void EGLCore::ChangeColor(){if (!eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {LOGE("EGLCore::eglMakeCurrent error = %{public}d", eglGetError());}GLfloat color[] = {0.9f, 0.5f, 0.7f, 1.0f};const GLfloat triangleVertices[] = {0.0f, 1.0f,-1.0f, -1.0f,1.0f, -1.0f};glViewport(0, 0, width_, height_);glClearColor(0.0, 0.0, 0.0, 1.0);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(mProgramHandle);GLint positionHandle = glGetAttribLocation(mProgramHandle, "a_position");glVertexAttribPointer(positionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);glEnableVertexAttribArray(positionHandle);glVertexAttrib4fv(1, color);glDrawArrays(GL_TRIANGLES, 0, 3);glDisableVertexAttribArray(positionHandle);Update();}void EGLCore::Update(){eglSwapBuffers(mEGLDisplay, mEGLSurface);}GLuint EGLCore::LoadShader(GLenum type, const char *shaderSrc){GLuint shader;GLint compiled;shader = glCreateShader(type);if (shader == 0) {LOGE("LoadShader shader error");return 0;}glShaderSource(shader, 1, &shaderSrc, nullptr);glCompileShader(shader);glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);if (!compiled) {GLint infoLen = 0;glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);if (infoLen > 1) {char *infoLog = (char*)malloc(sizeof(char) * infoLen);glGetShaderInfoLog(shader, infoLen, nullptr, infoLog);LOGE("Error compiling shader:\n%s\n",infoLog);free(infoLog);}glDeleteShader(shader);return 0;}return shader;}GLuint EGLCore::CreateProgram(const char *vertexShader, const char *fragShader){GLuint vertex;GLuint fragment;GLuint program;GLint linked;vertex = LoadShader(GL_VERTEX_SHADER, vertexShader);if (vertex == 0) {LOGE("CreateProgram vertex error");return 0;}fragment = LoadShader(GL_FRAGMENT_SHADER, fragShader);if (fragment == 0) {LOGE("CreateProgram fragment error");glDeleteShader(vertex);return 0;}program = glCreateProgram();if (program == 0) {LOGE("CreateProgram program error");glDeleteShader(vertex);glDeleteShader(fragment);return 0;}glAttachShader(program, vertex);glAttachShader(program, fragment);glLinkProgram(program);glGetProgramiv(program, GL_LINK_STATUS, &linked);if (!linked) {LOGE("CreateProgram linked error");GLint infoLen = 0;glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);if (infoLen > 1) {char *infoLog = (char *)malloc(sizeof(char) * infoLen);glGetProgramInfoLog(program, infoLen, nullptr, infoLog);LOGE("Error linking program:\n%s\n",infoLog);free(infoLog);}glDeleteShader(vertex);glDeleteShader(fragment);glDeleteProgram(program);return 0;}glDeleteShader(vertex);glDeleteShader(fragment);return program;}bool EGLCore::checkGlError(const char* op){LOGE("EGL ERROR CODE = %{public}x", eglGetError());GLint error;for (error = glGetError(); error; error = glGetError()) {LOGE("ERROR: %{public}s, ERROR CODE = %{public}x", op, error);return true;}return false;}

小结

通过上述方式,我们就能编译并安装运行应用了,上述代码链接在:https://toscode.gitee.com/openharmony/app_samples/tree/master/ETSUI/XComponent。

​​想了解更多关于开源的内容,请访问:​​

​​51CTO开源基础软件社区​​

​​https://ost.51cto.com​​。

责任编辑:jianghua 来源:51CTO 开源基础软件社区 鸿蒙HAP应用调用

推荐系统

  • 电脑公司Ghost Win8.1 x32 精选纯净版2022年7月(免激活) ISO镜像高速下载

    电脑公司Ghost Win8.1 x32 精选纯净版2022年7月(免激活) ISO镜像高速下载

    语言:中文版系统大小:2.98GB系统类型:Win8

    电脑公司Ghost Win8.1x32位纯净版V2022年7月版本集成了自2022流行的各种硬件驱动,首次进入系统即全部硬件已安装完毕。电脑公司Ghost Win8.1x32位纯净版具有更安全、更稳定、更人性化等特点。集成最常用的装机软件,精心挑选的系统维护工具,加上绿茶独有

  • 微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载

    微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载

    语言:中文版系统大小:5.13GB系统类型:Win11

    微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。Win11 64位 Office办公版(免费)优化  1、保留 Edge浏览器。  2、隐藏“操作中心”托盘图标。  3、保留常用组件(微软商店,计算器,图片查看器等)。  5、关闭天气资讯。 

  • Win11 21H2 官方正式版下载_Win11 21H2最新系统免激活下载

    Win11 21H2 官方正式版下载_Win11 21H2最新系统免激活下载

    语言:中文版系统大小:4.75GB系统类型:Win11

    Ghost Win11 21H2是微软在系统方面技术积累雄厚深耕多年,Ghost Win11 21H2系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。Ghost Win11 21H2是微软最新发布的KB5019961补丁升级而来的最新版的21H2系统,以Windows 11 21H2 22000 1219 专业版为基础进行优化,保持原汁原味,系统流畅稳定,保留常用组件

  • windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载

    windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载

    语言:中文版系统大小:5.31GB系统类型:Win11

    windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载,微软win11发布快大半年了,其中做了很多次补丁和修复一些BUG,比之前的版本有一些功能上的调整,目前已经升级到最新版本的镜像系统,并且优化了自动激活,永久使用。windows11中文版镜像国内镜像下载地址微软windows11正式版镜像 介绍:1、对函数算法进行了一定程度的简化和优化

  • 微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载

    微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载

    语言:中文版系统大小:5.31GB系统类型:Win11

    微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载,微软2022年正式推出了win11系统,很多人迫不及待的要体验,本站提供了最新版的微软Windows11正式版系统下载,微软windows11正式版镜像 是一款功能超级强大的装机系统,是微软方面全新推出的装机系统,这款系统可以通过pe直接的完成安装,对此系统感兴趣,想要使用的用户们就快来下载

  • 微软windows11系统下载 微软原版 Ghost win11 X64 正式版ISO镜像文件

    微软windows11系统下载 微软原版 Ghost win11 X64 正式版ISO镜像文件

    语言:中文版系统大小:0MB系统类型:Win11

    微软Ghost win11 正式版镜像文件是一款由微软方面推出的优秀全新装机系统,这款系统的新功能非常多,用户们能够在这里体验到最富有人性化的设计等,且全新的柔软界面,看起来非常的舒服~微软Ghost win11 正式版镜像文件介绍:1、与各种硬件设备兼容。 更好地完成用户安装并有效地使用。2、稳定使用蓝屏,系统不再兼容,更能享受无缝的系统服务。3、为

  • 雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载

    雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载

    语言:中文版系统大小:4.75GB系统类型:

    雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载在系统方面技术积累雄厚深耕多年,打造了国内重装系统行业的雨林木风品牌,其系统口碑得到许多人认可,积累了广大的用户群体,雨林木风是一款稳定流畅的系统,一直以来都以用户为中心,是由雨林木风团队推出的Windows11国内镜像版,基于国内用户的习惯,做了系统性能的优化,采用了新的系统

  • 雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO

    雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO

    语言:中文版系统大小:5.91GB系统类型:Win7

    雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO在系统方面技术积累雄厚深耕多年,加固了系统安全策略,雨林木风win7旗舰版系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。win7 32位旗舰装机版 v2019 05能够帮助用户们进行系统的一键安装、快速装机等,系统中的内容全面,能够为广大用户