#盲盒+码# #跟着小白一起学鸿蒙#HAP应用调用so库方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#盲盒+码# #跟着小白一起学鸿蒙#HAP应用调用so库方法相关的知识,希望对你有一定的参考价值。
作者:王石
概述
在《[#跟着小白一起学鸿蒙# 七] 写个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 @Component struct 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 SHARED render/egl_core.cpp render/plugin_render.cpp plugin_manager.cpp napi/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 <stdint.h> #include <string> #include <stdio.h> #include <ace/xcomponent/native_interface_xcomponent.h> #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<void**>(&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<uv_async_cb>(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 <stdint.h> #include "plugin_render.h" #include "plugin_common.h" #include "plugin_manager.h" #ifdef __cplusplus extern "C" #endif std::unordered_map<std::string, PluginRender*> 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 = %publicf, y = %publicf screenx = %publicf, screeny = %publicf", touchEvent_.x, touchEvent_.y, touchEvent_.screenX, touchEvent_.screenY); for (int i=0;i<touchEvent_.numPoints;i++) LOGE("Touch Info : dots[%publicd] id %publicd x = %publicf, y = %publicf", i, touchEvent_.touchPoints[i].id, touchEvent_.touchPoints[i].x, touchEvent_.touchPoints[i].y); LOGE("Touch Info : screenx = %publicf, screeny = %publicf", touchEvent_.touchPoints[i].screenX, touchEvent_.touchPoints[i].screenY); LOGE("vtimeStamp = %publicllu, isPressed = %publicd", touchEvent_.touchPoints[i].timeStamp, touchEvent_.touchPoints[i].isPressed); else LOGE("Touch fail"); napi_value PluginRender::Export(napi_env env, napi_value exports) LOGE("PluginRender::Export"); // Register JS API napi_property_descriptor desc[] = DECLARE_NAPI_FUNCTION("changeShape", PluginRender::NapiChangeShape), DECLARE_NAPI_FUNCTION("drawTriangle", PluginRender::NapiDrawTriangle), DECLARE_NAPI_FUNCTION("changeColor", PluginRender::NapiChangeColor), ; NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); return exports; napi_value PluginRender::NapiChangeShape(napi_env env, napi_callback_info info) LOGD("NapiChangeShape"); 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<void**>(&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<void**>(&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<void**>(&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 <EGL/egl.h> #include <GLES3/gl3.h> EGLConfig 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 = %publicp, w = %publicd, h = %publicd.", window, w, h); width_ = w; height_ = h; mEglWindow = static_cast<EGLNativeWindowType>(window); // 1. create sharedcontext mEGLDisplay = 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 Window EGLint 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 from int 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 = %publicd", 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 = %publicd", 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 = %publicd", 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 = %publicx", eglGetError()); GLint error; for (error = glGetError(); error; error = glGetError()) LOGE("ERROR: %publics, ERROR CODE = %publicx", op, error); return true; return false;
小结
通过上述方式,我们就能编译并安装运行应用了,上述代码链接在:https://toscode.gitee.com/openharmony/app_samples/tree/master/ETSUI/XComponent
本文作者:左翼风发
https://ost.51cto.com/#bkwz
以上是关于#盲盒+码# #跟着小白一起学鸿蒙#HAP应用调用so库方法的主要内容,如果未能解决你的问题,请参考以下文章
#盲盒+码# #跟着小白一起学鸿蒙# [番外]一起学做Tetris(下)
#盲盒+码##跟着小白一起学鸿蒙#如何编译OpenHarmony自带APP
#盲盒+码# #跟着小白一起学鸿蒙#OpenHarmony调试工具
#冲刺创作新星# #跟着小白一起学鸿蒙# [七] 写个NAPI子系统