建立应用侧与前端页面数据通道(C/C++)
=====================

前端页面和应用侧之间可以使用Native方法实现两端通信（以下简称Native PostWebMessage），可解决ArkTS环境的冗余切换，同时允许发送消息、回调在非UI线程上运行，避免造成UI阻塞。当前只支持string和buffer数据类型。

#### 适用的应用架构

应用使用ArkTS、C++语言混合开发，或本身应用架构较贴近于小程序架构，自带C++侧环境，推荐使用ArkWeb在Native侧提供的[ArkWeb\_ControllerAPI](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-web-arkweb-controllerapi)、[ArkWeb\_WebMessageAPI](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-web-arkweb-webmessageapi)、[ArkWeb\_WebMessagePortAPI](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-web-arkweb-webmessageportapi)实现PostWebMessage功能。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/6c/v3/__xcoMUHTQ-91zeGCEb9dg/zh-cn_image_0000002664208003.png?HW-CC-KV=V1&HW-CC-Date=20260709T132332Z&HW-CC-Expire=86400&HW-CC-Sign=CCC34E3255D9D341E63CE5AE91DB47F8B404199F282C20A9F3E99D7ECAEF7DBE)

上图展示了具有普遍适用性的小程序的通用架构。在这一架构中，逻辑层依赖于应用程序自带的JavaScript运行时，该运行时在一个已有的C++环境中运行。通过Native接口，逻辑层能够直接在C++环境中与视图层（其中ArkWeb充当渲染器）进行通信，无需回退至ArkTS环境使用ArkTS PostWebMessage接口。

左图是使用ArkTS PostWebMessage接口构建小程序的方案，如红框所示，应用需要先调用到ArkTS环境，再调用到C++环境。右图是使用Native PostWebMessage接口构建小程序的方案，不需要ArkTS环境和C++环境的切换，执行效率更高。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/72/v3/mQf8nRlcRimEz77vTKaDUQ/zh-cn_image_0000002633848952.png?HW-CC-KV=V1&HW-CC-Date=20260709T132332Z&HW-CC-Expire=86400&HW-CC-Sign=98EA9C7EFFAE646114AF93F5B9DD824BC9FA8480917441998BA90592FA658EE0)

#### 使用Native接口实现PostWebMessage通信

#### \[h2\]使用Native接口绑定ArkWeb

*   ArkWeb组件声明在ArkTS侧，需要用户自定义一个标识webTag，并将webTag通过Node-API传至应用C++侧。后续ArkWeb Native接口使用时，均需webTag作为对应组件的唯一标识。
    
*   ArkTS侧
    
    import { webview } from '@kit.ArkWeb';
    // 自定义webTag，在WebviewController创建时作为入参传入，建立controller与webTag的映射关系
    webTag: string = 'ArkWeb1';
    controller: webview.WebviewController = new webview.WebviewController(this.webTag);
    // ...
    // aboutToAppear中将webTag通过Node-API接口传入C++侧，作为C++侧ArkWeb组件的唯一标识
    aboutToAppear() {
      console.info("aboutToAppear")
      // 初始化web ndk
      testNapi.nativeWebInit(this.webTag);
    }
    // ...
    

#### \[h2\]使用Native接口获取API结构体

ArkWeb Native侧需先获取API结构体，才能调用结构体里的Native API。ArkWeb Native侧API通过函数[OH\_ArkWeb\_GetNativeAPI](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-arkweb-interface-h#oh_arkweb_getnativeapi)获取，根据入参type不同，可获取对应的函数指针结构体。其中本指导涉及[ArkWeb\_ControllerAPI](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-web-arkweb-controllerapi)、[ArkWeb\_WebMessageAPI](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-web-arkweb-webmessageapi)、[ArkWeb\_WebMessagePortAPI](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-web-arkweb-webmessageportapi)。

static ArkWeb\_ControllerAPI \*controller = nullptr;
static ArkWeb\_WebMessagePortAPI \*webMessagePort = nullptr;
static ArkWeb\_WebMessageAPI \*webMessage = nullptr;
// ...
controller = reinterpret\_cast<ArkWeb\_ControllerAPI \*>(OH\_ArkWeb\_GetNativeAPI(ARKWEB\_NATIVE\_CONTROLLER));
webMessagePort =
    reinterpret\_cast<ArkWeb\_WebMessagePortAPI \*>(OH\_ArkWeb\_GetNativeAPI(ARKWEB\_NATIVE\_WEB\_MESSAGE\_PORT));
webMessage = reinterpret\_cast<ArkWeb\_WebMessageAPI \*>(OH\_ArkWeb\_GetNativeAPI(ARKWEB\_NATIVE\_WEB\_MESSAGE));

#### \[h2\]完整示例

在调用API前建议通过[ARKWEB\_MEMBER\_MISSING](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-arkweb-type-h#宏定义)校验该函数结构体是否有对应函数指针，避免SDK与设备ROM不匹配导致crash问题。[createWebMessagePorts](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-web-arkweb-controllerapi#createwebmessageports)、[postWebMessage](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-web-arkweb-controllerapi#postwebmessage)、[close](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-web-arkweb-webmessageportapi#close)需运行在UI线程。

*   前端页面代码
    
    <!-- entry/src/main/resources/rawfile/index.html -->
    <!-- index.html -->
    <!DOCTYPE html>
    <html lang="en-gb">
    <body>
    <h1>etsRunJavaScriptExt测试demo</h1>
    <h1 id="h1"></h1>
    <h3 id="msg">Receive string:</h3>
    <h3 id="msg2">Receive arraybuffer:</h3>
    
    </body>
    <script type="text/javascript">
    var h5Port;
    
    window.addEventListener('message', function (event) {
        if (event.data == 'init\_web\_messageport') {
            const port = event.ports\[0\]; // 1. 保存从应用侧发送过来的端口。
            if (port) {
                console.info("hwd In html got message");
                h5Port = port;
                port.onmessage = function (event) {
                    console.info("hwd In html got message");
                    // 2. 接收应用侧发送过来的消息.
                    var result = event.data;
                    var type\_s = typeof (result)
                    switch (type\_s) {
                        case "object":
                            if (result instanceof ArrayBuffer) {
                                type\_s = "ArrayBuffer";
                                var view = new Uint8Array(result);
                                const decoder = new TextDecoder('utf-8');
                                result = decoder.decode(result);
                            } else if (result instanceof Error) {
                                type\_s = "Error";
                            } else if (result instanceof Array) {
                                type\_s = "Array";
                            }
                            break;
                        default:
                            break;
                    }
                    console.info("H5 recv type: " + type\_s + "\\nH5 recv result: " + result)
                    document.getElementById("msg").innerHTML = "recv type: " + type\_s;
                    document.getElementById("msg2").innerHTML = "recv value: " + result;
                }
                h5Port.onmessageerror = (event) => {
                    console.error(\`hwd In html Error receiving message: ${event}\`);
                };
            }
        }
    })
    window.onerror = function(message, url, line, column, error) {
      console.info("JavaScript Error: " + message + " on line " + line + " in " + url);
      document.getElementById("h1").innerHTML = "执行函数失败"
    };
    
    // 3. 使用h5Port向应用侧发送消息。
    function postStringToApp() {
        if (h5Port) {
            h5Port.postMessage("send string from H5");
        } else {
            console.error("In html h5port is null, please init first");
        }
    }
    function postBufferToApp() {
        if (h5Port) {
            const str = "Hello, World!";
            const encoder = new TextEncoder();
            const uint8Array = encoder.encode(str);
            h5Port.postMessage(uint8Array.buffer);
        } else {
            console.error("In html h5port is null, please init first");
        }
    }
    
    function postJsonToApp() {
        if (h5Port) {
            var e = {"json": "json"};
            h5Port.postMessage(e);
        } else {
            console.error("In html h5port is null, please init first");
        }
    }
    
    function postArrayStringToApp() {
        if (h5Port) {
            h5Port.postMessage(\["1", "2", "3"\]);
        } else {
            console.error("In html h5port is null, please init first");
        }
    }
    
    function postNumberToApp() {
        if (h5Port) {
            h5Port.postMessage(123);
        } else {
            console.error("In html h5port is null, please init first");
        }
    }
    class MyClass {
      constructor() {
        // 构造器
        this.myProperty = 'Hello, World!';
      }
    
      myMethod() {
        // 实例方法
        console.info(this.myProperty);
      }
    
      static myStaticMethod() {
        // 静态方法
        console.info('This is a static method.');
      }
    }
    function postObjectToApp() {
        if (h5Port) {
            h5Port.postMessage(new MyClass());
        } else {
            console.error("In html h5port is null, please init first");
        }
    }
    
    </script>
    </html>
    
*   ArkTS侧代码
    
    import testNapi from 'libentry.so';
    import { webview } from '@kit.ArkWeb';
    import { BusinessError } from '@kit.BasicServicesKit';
    
    @Entry
    @Component
    struct Index {
      @State webTag: string = 'postMessage';
      controller: webview.WebviewController = new webview.WebviewController(this.webTag);
      @State h5Log: string = 'Display received message send from HTML';
    
      aboutToAppear() {
        webview.WebviewController.setWebDebuggingAccess(true);
        // 初始化web Native Development Kit
        testNapi.nativeWebInit(this.webTag);
      }
    
      aboutToDisAppear() {
        console.error('aboutToDisAppear');
      }
    
      build() {
        Scroll() {
          Column({ space: 10 }) {
            // 展示H5接收到的内容
            Text('H5\_Side\_Message\_Display\_From\_App')
            TextArea({text: this.h5Log})
              .id('log\_area')
              .width('100%')
              .height(100)
              .border({ width: 1 })
            Text('App\_Side\_Button')
            Row() {
              Button('createNoControllerTagPort')
                .id('create\_no\_tag\_btn')
                .onClick(() => {
                  try {
                    testNapi.createWebMessagePorts('noTag');
                  } catch (error) {
                    console.error(
                      \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                  }
                })
              Button('createPort')
                .id('create\_port\_btn')
                .onClick(() => {
                  try {
                    testNapi.createWebMessagePorts(this.webTag);
                  } catch (error) {
                    console.error(
                      \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                  }
                })
            }
    
            Row({ space: 10 }) {
    
              Button('setHandler')
                .id('set\_handler\_btn')
                .onClick(() => {
                  try {
                    testNapi.setMessageEventHandler(this.webTag);
                  } catch (error) {
                    console.error(
                      \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                  }
                })
    
              Button('setHandlerThread')
                .id('set\_handler\_thread\_btn')
                .onClick(() => {
                  try {
                    testNapi.setMessageEventHandlerThread(this.webTag);
                  } catch (error) {
                    console.error(
                      \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                  }
                })
            }
    
            Row({ space: 10 }) {
              Button('SendString')
                .id('send\_string\_btn')
                .onClick(() => {
                  try {
                    this.h5Log = ''
                    testNapi.postMessage(this.webTag);
                  } catch (error) {
                    console.error(
                      \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                  }
                })
              Button('SendStringThread')
                .id('send\_string\_thread\_btn')
                .onClick(() => {
                  try {
                    this.h5Log = ''
                    testNapi.postMessageThread(this.webTag);
                  } catch (error) {
                    console.error(
                      \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                  }
                })
            }
    
            Row({ space: 10 }) {
              Button('SendBuffer')
                .id('send\_buffer\_btn')
                .onClick(() => {
                  try {
                    this.h5Log = ''
                    testNapi.postBufferMessage(this.webTag);
                  } catch (error) {
                    console.error(
                      \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                  }
                })
              Button('SendNone')
                .id('send\_none\_btn')
                .onClick(() => {
                  try {
                    this.h5Log = ''
                    testNapi.postNoneMessage(this.webTag);
                  } catch (error) {
                    console.error(
                      \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                  }
                })
            }
    
            Row({ space: 10 }) {
    
              Button('closePort')
                .id('close\_port\_btn')
                .onClick(() => {
                  try {
                    testNapi.closeMessagePort(this.webTag);
                  } catch (error) {
                    console.error(
                      \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                  }
                })
              Button('destroyNullPort')
                .id('destroy\_null\_btn')
                .onClick(() => {
                  try {
                    testNapi.destroyNullMessagePort(this.webTag);
                  } catch (error) {
                    console.error(
                      \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                  }
                })
              Button('destroyPort')
                .id('destroy\_port\_btn')
                .onClick(() => {
                  try {
                    testNapi.destroyMessagePort(this.webTag);
                  } catch (error) {
                    console.error(
                      \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                  }
                })
            }
            .width('100%')
            .padding(10)
            .border({ width: 1 })
    
            Column({ space: 10 }) {
              Text('H5\_Side\_Send\_Button')
              Row({ space: 10 }) {
                Button('H5String')
                  .id('h5\_send\_string\_btn')
                  .onClick(() => {
                    try {
                      this.controller.runJavaScript('for(var i = 0; i < 2000; i++) postStringToApp()');
                    } catch (error) {
                      console.error(
                        \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                    }
                  })
                Button('H5Buffer')
                  .id('h5\_send\_buffer\_btn')
                  .onClick(() => {
                    try {
                      this.controller.runJavaScript('postBufferToApp()');
                    } catch (error) {
                      console.error(
                        \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                    }
                  })
                Button('H5Number')
                  .id('h5\_send\_number\_btn')
                  .onClick(() => {
                    try {
                      this.controller.runJavaScript('postNumberToApp()');
                    } catch (error) {
                      console.error(
                        \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                    }
                  })
              }
    
              Row({ space: 10 }) {
                Button('H5Json')
                  .id('h5\_send\_json\_btn')
                  .onClick(() => {
                    try {
                      this.controller.runJavaScript('postJsonToApp()');
                    } catch (error) {
                      console.error(
                        \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                    }
                  })
                Button('H5Array')
                  .id('h5\_send\_array\_btn')
                  .onClick(() => {
                    try {
                      this.controller.runJavaScript('postArrayStringToApp()');
                    } catch (error) {
                      console.error(
                        \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                    }
                  })
                Button('H5Object')
                  .id('h5\_send\_object\_btn')
                  .onClick(() => {
                    try {
                      this.controller.runJavaScript('postObjectToApp()');
                    } catch (error) {
                      console.error(
                        \`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}\`);
                    }
                  })
              }
            }
            .width('100%')
            .margin(10)
            .padding(10)
            .border({ width: 1 })
    
            Web({ src: $rawfile('index.html'), controller: this.controller })
              .onConsole((event) => {
                if (event) {
                  let msg = event.message.getMessage();
                  if (msg.startsWith('H5')) {
                    this.h5Log = event.message.getMessage() + '\\n' + this.h5Log;
                  }
                }
                return false;
              })
          }
        }.height('100%')
        .scrollable(ScrollDirection.Vertical)
        .scrollBar(BarState.Off)
        .edgeEffect(EdgeEffect.Spring)
      }
    }
    
*   Node-API侧暴露ArkTS接口
    
    // entry5/src/main/cpp/types/libentry5/index.d.ts
    export const nativeWebInit: (webName: string) => void;
    export const createWebMessagePorts: (webName: string) => void;
    export const postMessage: (webName: string) => void;
    export const postNoneMessage: (webName: string) => void;
    export const setMessageEventHandler: (webName: string) => void;
    export const closeMessagePort: (webName: string) => void;
    export const destroyMessagePort: (webName: string) => void;
    export const postBufferMessage: (webName: string) => void;
    export const destroyNullMessagePort: (webName: string) => void;
    export const setMessageEventHandlerThread: (webName: string) => void;
    export const postMessageThread: (webName: string) => void;
    
*   Node-API侧编译配置
    
    \# entry/src/main/cpp/CMakeLists.txt
    # the minimum version of CMake.
    cmake\_minimum\_required(VERSION 3.4.1)
    project(NDKPostMessage)
    
    set(NATIVERENDER\_ROOT\_PATH ${CMAKE\_CURRENT\_SOURCE\_DIR})
    
    if(DEFINED PACKAGE\_FIND\_FILE)
        include(${PACKAGE\_FIND\_FILE})
    endif()
    
    include\_directories(${NATIVERENDER\_ROOT\_PATH}
                        ${NATIVERENDER\_ROOT\_PATH}/include)
    
    add\_library(entry SHARED hello.cpp)
    
    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
    )
    
    target\_link\_libraries(entry PUBLIC libace\_napi.z.so ${hilog-lib} libohweb.so)
    
*   Node-API层代码
    
    #include "hilog/log.h"
    #include "napi/native\_api.h"
    #include "web/arkweb\_interface.h"
    #include <string>
    #include <thread>
    
    constexpr unsigned int LOG\_PRINT\_DOMAIN = 0xFF00;
    ArkWeb\_ControllerAPI \*controller = nullptr;
    
    ArkWeb\_WebMessagePortAPI \*webMessagePort = nullptr;
    ArkWeb\_WebMessageAPI \*webMessage = nullptr;
    size\_t g\_webMessagePortSize = 0;
    ArkWeb\_WebMessagePortPtr \*g\_web\_message\_port\_arr = nullptr;
    
    static void WebMessagePortCallback(
        const char \*webTag, const ArkWeb\_WebMessagePortPtr port, const ArkWeb\_WebMessagePtr message, void \*userData)
    {
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit WebMessagePortCallback webTag:%{public}s,messageType:%{public}d",
            webTag, webMessage->getType(message));
        size\_t len = 0;
        void \*back = webMessage->getData(message, &len);
        if (webMessage->getType(message) == ArkWeb\_WebMessageType::ARKWEB\_STRING) {
            OH\_LOG\_Print(
                LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
                "Native Development Kit WebMessagePortCallback message:%{public}s,messageSize:%{public}d", back, len);
        } else if (webMessage->getType(message) == ArkWeb\_WebMessageType::ARKWEB\_BUFFER) {
            OH\_LOG\_Print(
                LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
                "Native Development Kit WebMessagePortCallback messageSize:%{public}d", len);
        }
    }
    
    static napi\_value NativeWebInit(napi\_env env, napi\_callback\_info info)
    {
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb", "Native Development Kit NativeWebInit start");
        size\_t argc = 1;
        napi\_value args\[1\] = {nullptr};
        napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
        // 获取第一个参数webTag
        size\_t webTagSize = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], nullptr, 0, &webTagSize);
        char \*webTagValue = new (std::nothrow) char\[webTagSize + 1\];
        size\_t webTagLength = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], webTagValue, webTagSize + 1, &webTagLength);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_ERROR, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit NativeWebInit webTag:%{public}s", webTagValue);
    
        controller = reinterpret\_cast<ArkWeb\_ControllerAPI \*>(OH\_ArkWeb\_GetNativeAPI(ARKWEB\_NATIVE\_CONTROLLER));
        if (controller)
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, LOG\_PRINT\_DOMAIN, "ArkWeb", "get ArkWeb\_ControllerAPI success");
    
        webMessagePort =
            reinterpret\_cast<ArkWeb\_WebMessagePortAPI \*>(OH\_ArkWeb\_GetNativeAPI(ARKWEB\_NATIVE\_WEB\_MESSAGE\_PORT));
        if (webMessagePort)
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, LOG\_PRINT\_DOMAIN, "ArkWeb", "get ArkWeb\_WebMessagePortAPI success");
    
        webMessage = reinterpret\_cast<ArkWeb\_WebMessageAPI \*>(OH\_ArkWeb\_GetNativeAPI(ARKWEB\_NATIVE\_WEB\_MESSAGE));
        if (webMessage)
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, LOG\_PRINT\_DOMAIN, "ArkWeb", "get ArkWeb\_WebMessageAPI success");
    
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb", "Native Development Kit NativeWebInit end");
        delete\[\] webTagValue;
        return nullptr;
    }
    
    static napi\_value createWebMessagePorts(napi\_env env, napi\_callback\_info info)
    {
        size\_t argc = 2;
        napi\_value args\[2\] = {nullptr};
        napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
    
        // 获取第一个参数webTag
        size\_t webTagSize = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], nullptr, 0, &webTagSize);
        char \*webTagValue = new (std::nothrow) char\[webTagSize + 1\];
        size\_t webTagLength = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], webTagValue, webTagSize + 1, &webTagLength);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit Refresh webTag:%{public}s", webTagValue);
    
        // 初始化端口
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb", "Native Development Kit createWebMessagePorts begin");
        g\_web\_message\_port\_arr = controller->createWebMessagePorts(webTagValue, &g\_webMessagePortSize);
        // 把其中一个端口发送给HTML
        ArkWeb\_ErrorCode code =
            controller->postWebMessage(webTagValue, "init\_web\_messageport", g\_web\_message\_port\_arr, 1, "\*");
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit postWebMessage ArkWeb\_ErrorCode:%{public}d", code);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit createWebMessagePorts end, web message port size:%{public}d", g\_webMessagePortSize);
        delete\[\] webTagValue;
        return nullptr;
    }
    
    static napi\_value postMessage(napi\_env env, napi\_callback\_info info)
    {
        size\_t argc = 2;
        napi\_value args\[2\] = {nullptr};
        napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
    
        // 获取第一个参数webTag
        size\_t webTagSize = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], nullptr, 0, &webTagSize);
        char \*webTagValue = new (std::nothrow) char\[webTagSize + 1\];
        size\_t webTagLength = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], webTagValue, webTagSize + 1, &webTagLength);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit Refresh webTag:%{public}s", webTagValue);
    
        // 发送消息
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb", "Native Development Kit postMessage begin");
    
        if (g\_web\_message\_port\_arr == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, LOG\_PRINT\_DOMAIN, "ArkWeb", "webMessagePort is nullptr");
            return nullptr;
        }
        ArkWeb\_WebMessagePtr message = webMessage->createWebMessage();
        webMessage->setType(message, ArkWeb\_WebMessageType::ARKWEB\_STRING);
        std::string str = "send string from native";
        webMessage->setData(message, (void \*)str.c\_str(), str.length() + 1);
        ArkWeb\_ErrorCode code = webMessagePort->postMessage(g\_web\_message\_port\_arr\[1\], webTagValue, message);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit postMessage ArkWeb\_ErrorCode:%{public}d", code);
        webMessage->destroyWebMessage(&message);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit postMessage end, web message port size:%{public}d", g\_webMessagePortSize);
        delete\[\] webTagValue;
        return nullptr;
    }
    
    
    // 在线程中发消息
    void sendMessage(const char \*webTag, const ArkWeb\_WebMessagePtr message)
    {
        // 发送1000次
        for (int i = 0; i < 1000; i++) {
            OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb", "sendMessage in thread %{public}d", i);
            if (g\_web\_message\_port\_arr && webTag && message) {
                    webMessagePort->postMessage(g\_web\_message\_port\_arr\[1\], webTag, message);
            }
        }
    }
    static napi\_value postMessageThread(napi\_env env, napi\_callback\_info info)
    {
        size\_t argc = 2;
        napi\_value args\[2\] = {nullptr};
        napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
    
        // 获取第一个参数webTag
        size\_t webTagSize = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], nullptr, 0, &webTagSize);
        char \*webTagValue = new (std::nothrow) char\[webTagSize + 1\];
        size\_t webTagLength = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], webTagValue, webTagSize + 1, &webTagLength);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit Refresh webTag:%{public}s", webTagValue);
    
        // 构造消息
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb", "Native Development Kit postMessage begin");
    
        if (g\_web\_message\_port\_arr == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, LOG\_PRINT\_DOMAIN, "ArkWeb", "webMessagePort is nullptr");
            return nullptr;
        }
        ArkWeb\_WebMessagePtr message = webMessage->createWebMessage();
        webMessage->setType(message, ArkWeb\_WebMessageType::ARKWEB\_STRING);
        std::string str = "thread message";
        webMessage->setData(message, (void \*)str.c\_str(), str.length() + 1);
        const int numThreads = 5;
        std::thread threads\[numThreads\];
    
        // 创建线程
        for (int i = 0; i < numThreads; ++i) {
            threads\[i\] = std::thread(sendMessage, webTagValue, message);
        }
    
        // 等待所有线程完成
        for (int i = 0; i < numThreads; ++i) {
            threads\[i\].join();
        }
        delete\[\] webTagValue;
        return nullptr;
    }
    
    // 在线程中注册回调
    void SetHandler(const char \*webTag)
    {
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb", "setMessageEventHandler in thread");
        webMessagePort->setMessageEventHandler(g\_web\_message\_port\_arr\[1\], webTag, WebMessagePortCallback, NULL);
    }
    
    static napi\_value setMessageEventHandlerThread(napi\_env env, napi\_callback\_info info)
    {
        size\_t argc = 2;
        napi\_value args\[2\] = {nullptr};
        napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
    
        // 获取第一个参数webTag
        size\_t webTagSize = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], nullptr, 0, &webTagSize);
        char \*webTagValue = new (std::nothrow) char\[webTagSize + 1\];
        size\_t webTagLength = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], webTagValue, webTagSize + 1, &webTagLength);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit Refresh webTag:%{public}s", webTagValue);
    
        // 注册回调
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit SetMessageEventHandler begin");
        if (g\_web\_message\_port\_arr == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, LOG\_PRINT\_DOMAIN, "ArkWeb", "webMessagePort is nullptr");
            return nullptr;
        }
        std::thread thread(SetHandler, webTagValue);
        thread.detach();
        webMessagePort->setMessageEventHandler(g\_web\_message\_port\_arr\[1\], webTagValue, WebMessagePortCallback, NULL);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit SetMessageEventHandler end, web message port size:%{public}d", g\_webMessagePortSize);
        delete\[\] webTagValue;
        return nullptr;
    }
    static napi\_value postNoneMessage(napi\_env env, napi\_callback\_info info)
    {
        size\_t argc = 2;
        napi\_value args\[2\] = {nullptr};
        napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
    
        // 获取第一个参数webTag
        size\_t webTagSize = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], nullptr, 0, &webTagSize);
        char \*webTagValue = new (std::nothrow) char\[webTagSize + 1\];
        size\_t webTagLength = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], webTagValue, webTagSize + 1, &webTagLength);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN,
            "ArkWeb", "Native Development Kit Refresh webTag:%{public}s", webTagValue);
    
        // 发送消息
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb", "Native Development Kit 发消息开始");
    
        if (g\_web\_message\_port\_arr == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, LOG\_PRINT\_DOMAIN, "ArkWeb", "webMessagePort is nullptr");
            return nullptr;
        }
        ArkWeb\_WebMessagePtr message = webMessage->createWebMessage();
        webMessage->setType(message, ArkWeb\_WebMessageType::ARKWEB\_NONE);
        std::string str = "send string from native";
        webMessage->setData(message, (void \*)str.c\_str(), str.length() + 1);
        webMessagePort->postMessage(g\_web\_message\_port\_arr\[1\], webTagValue, message);
        webMessage->destroyWebMessage(&message);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit postMessage end, web message port size:%{public}d", g\_webMessagePortSize);
        delete\[\] webTagValue;
        return nullptr;
    }
    
    static napi\_value postBufferMessage(napi\_env env, napi\_callback\_info info)
    {
        size\_t argc = 2;
        napi\_value args\[2\] = {nullptr};
        napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
    
        // 获取第一个参数webTag
        size\_t webTagSize = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], nullptr, 0, &webTagSize);
        char \*webTagValue = new (std::nothrow) char\[webTagSize + 1\];
        size\_t webTagLength = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], webTagValue, webTagSize + 1, &webTagLength);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit Refresh webTag:%{public}s", webTagValue);
    
        // 发送消息
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb", "Native Development Kit postMessage begin");
    
        if (g\_web\_message\_port\_arr == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, LOG\_PRINT\_DOMAIN, "ArkWeb", "webMessagePort is nullptr");
            return nullptr;
        }
        ArkWeb\_WebMessagePtr message1 = webMessage->createWebMessage();
        webMessage->setType(message1, ArkWeb\_WebMessageType::ARKWEB\_BUFFER);
        std::string str1 = "send buffer from native";
        webMessage->setData(message1, (void \*)str1.c\_str(), str1.length()+1);
        webMessagePort->postMessage(g\_web\_message\_port\_arr\[1\], webTagValue, message1);
        webMessage->destroyWebMessage(&message1);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit postMessage end, web message port size:%{public}d", g\_webMessagePortSize);
        delete\[\] webTagValue;
        return nullptr;
    }
    
    static napi\_value setMessageEventHandler(napi\_env env, napi\_callback\_info info)
    {
        size\_t argc = 2;
        napi\_value args\[2\] = {nullptr};
        napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
    
        // 获取第一个参数webTag
        size\_t webTagSize = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], nullptr, 0, &webTagSize);
        char \*webTagValue = new (std::nothrow) char\[webTagSize + 1\];
        size\_t webTagLength = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], webTagValue, webTagSize + 1, &webTagLength);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit Refresh webTag:%{public}s", webTagValue);
    
        // 注册回调
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb", "Native Development Kit SetMessageEventHandler begin");
        if (g\_web\_message\_port\_arr == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, LOG\_PRINT\_DOMAIN, "ArkWeb", "webMessagePort is nullptr");
            return nullptr;
        }
        webMessagePort->setMessageEventHandler(g\_web\_message\_port\_arr\[1\], webTagValue, WebMessagePortCallback, NULL);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit SetMessageEventHandler end, web message port size:%{public}d", g\_webMessagePortSize);
        delete\[\] webTagValue;
        return nullptr;
    }
    
    static napi\_value closeMessagePort(napi\_env env, napi\_callback\_info info)
    {
        size\_t argc = 2;
        napi\_value args\[2\] = {nullptr};
        napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
    
        // 获取第一个参数webTag
        size\_t webTagSize = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], nullptr, 0, &webTagSize);
        char \*webTagValue = new (std::nothrow) char\[webTagSize + 1\];
        size\_t webTagLength = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], webTagValue, webTagSize + 1, &webTagLength);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit Refresh webTag:%{public}s", webTagValue);
    
        // 关闭端口，先调用close，再调用destroyWebMessagePorts
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb", "Native Development Kit SetMessageEventHandler begin");
        if (g\_web\_message\_port\_arr == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, LOG\_PRINT\_DOMAIN, "ArkWeb", "webMessagePort is nullptr");
            return nullptr;
        }
        webMessagePort->close(g\_web\_message\_port\_arr\[0\], webTagValue);
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit SetMessageEventHandler end, web message port size:%{public}d", g\_webMessagePortSize);
        controller->refresh(webTagValue);
        delete\[\] webTagValue;
        return nullptr;
    }
    
    static napi\_value destroyMessagePort(napi\_env env, napi\_callback\_info info)
    {
        size\_t argc = 2;
        napi\_value args\[2\] = {nullptr};
        napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
    
        // 获取第一个参数webTag
        size\_t webTagSize = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], nullptr, 0, &webTagSize);
        char \*webTagValue = new (std::nothrow) char\[webTagSize + 1\];
        size\_t webTagLength = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], webTagValue, webTagSize + 1, &webTagLength);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit Refresh webTag:%{public}s", webTagValue);
    
        // 释放内存，先调用close，再调用destroyWebMessagePorts
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb", "Native Development Kit SetMessageEventHandler begin");
        if (g\_web\_message\_port\_arr == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, LOG\_PRINT\_DOMAIN, "ArkWeb", "webMessagePort is nullptr");
            return nullptr;
        }
        controller->destroyWebMessagePorts(&g\_web\_message\_port\_arr, g\_webMessagePortSize);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit SetMessageEventHandler end, web message port size:%{public}d", g\_webMessagePortSize);
        delete\[\] webTagValue;
        return nullptr;
    }
    
    static napi\_value destroyNullMessagePort(napi\_env env, napi\_callback\_info info)
    {
        size\_t argc = 2;
        napi\_value args\[2\] = {nullptr};
        napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
    
        // 获取第一个参数webTag
        size\_t webTagSize = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], nullptr, 0, &webTagSize);
        char \*webTagValue = new (std::nothrow) char\[webTagSize + 1\];
        size\_t webTagLength = 0;
        napi\_get\_value\_string\_utf8(env, args\[0\], webTagValue, webTagSize + 1, &webTagLength);
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit Refresh webTag:%{public}s", webTagValue);
    
        // 释放内存，先调用close，再调用destroyWebMessagePorts
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb", "Native Development Kit SetMessageEventHandler begin");
    
        controller->destroyWebMessagePorts(&g\_web\_message\_port\_arr, g\_webMessagePortSize);
    
        OH\_LOG\_Print(
            LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, "ArkWeb",
            "Native Development Kit SetMessageEventHandler end, web message port size:%{public}d", g\_webMessagePortSize);
        delete\[\] webTagValue;
        return nullptr;
    }
    
    EXTERN\_C\_START
    static napi\_value Init(napi\_env env, napi\_value exports)
    {
        napi\_property\_descriptor desc\[\] = {
            {"nativeWebInit", nullptr, NativeWebInit, nullptr, nullptr, nullptr, napi\_default, nullptr},
            {"createWebMessagePorts", nullptr, createWebMessagePorts, nullptr, nullptr, nullptr, napi\_default, nullptr},
            {"postMessage", nullptr, postMessage, nullptr, nullptr, nullptr, napi\_default, nullptr},
            {"postNoneMessage", nullptr, postNoneMessage, nullptr, nullptr, nullptr, napi\_default, nullptr},
            {"postBufferMessage", nullptr, postBufferMessage, nullptr, nullptr, nullptr, napi\_default, nullptr},
            {"setMessageEventHandler", nullptr, setMessageEventHandler, nullptr, nullptr, nullptr, napi\_default, nullptr},
            {"closeMessagePort", nullptr, closeMessagePort, nullptr, nullptr, nullptr, napi\_default, nullptr},
            {"destroyMessagePort", nullptr, destroyMessagePort, nullptr, nullptr, nullptr, napi\_default, nullptr},
            {"postMessageThread", nullptr, postMessageThread, nullptr, nullptr, nullptr, napi\_default, nullptr},
            {"setMessageEventHandlerThread", nullptr, setMessageEventHandlerThread, nullptr, nullptr, nullptr,
                napi\_default, nullptr},
            {"destroyNullMessagePort", nullptr, destroyNullMessagePort, nullptr, nullptr, nullptr, napi\_default, nullptr},
        };
        napi\_define\_properties(env, exports, sizeof(desc) / sizeof(desc\[0\]), desc);
        return exports;
    }
    EXTERN\_C\_END
    
    static napi\_module demoModule = {
        .nm\_version = 1,
        .nm\_flags = 0,
        .nm\_filename = nullptr,
        .nm\_register\_func = Init,
        .nm\_modname = "entry",
        .nm\_priv = ((void \*)0),
        .reserved = {0},
    };
    
    extern "C" \_\_attribute\_\_((constructor)) void RegisterEntryModule(void) { napi\_module\_register(&demoModule); }