#盲盒+码# #跟着小白一起学鸿蒙#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

  1. 接口

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

    参数:

    参数名 参数类型 必填 描述
    id string 组件的唯一标识,支持最大的字符串长度128。
    type string 用于指定XComponent组件类型,可选值为: -surface:组件内容单独送显,直接合成到屏幕。 -component:组件内容与其他组件合成后统一送显。
    libraryname string 应用Native层编译输出动态库名称。
    controller XComponentcontroller 给组件绑定一个控制器,通过控制器调用组件方法。
  2. 事件

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

      参数:

      参数名 参数类型 必填 描述
      event object 获取XComponent实例对象的context,context上挂载的方法由开发者在c++层定义。
    • 插件卸载完毕后的回调(onDestroy):onDestroy(event: () => void )

  3. 获取C++实例对象接口

    getXComponentContext()

    返回值:

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

样例开发

  1. 应用层开发

    和一般的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%)
      
    
    
    1. 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

本文作者:左翼风发

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

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

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

以上是关于#盲盒+码# #跟着小白一起学鸿蒙#HAP应用调用so库方法的主要内容,如果未能解决你的问题,请参考以下文章

#盲盒+码# #跟着小白一起学鸿蒙# [番外]一起学做Tetris(下)

#盲盒+码##跟着小白一起学鸿蒙#如何编译OpenHarmony自带APP

#盲盒+码# #跟着小白一起学鸿蒙#OpenHarmony调试工具

#冲刺创作新星# #跟着小白一起学鸿蒙# [七] 写个NAPI子系统

#跟着小白一起学鸿蒙# [番外]一起学做FlappyBird

#盲盒+码# #跟着小白一起学鸿蒙#简析OpenHarmony的WiFi能力