如何定位应用中Native层出现的空指针解引用CppCrash
===============================

#### 问题现象

长稳测试的时候，偶现CppCrash崩溃，每次的崩溃栈不同，复现的场景不明确。查看多个崩溃日志都有出现SIGSEGV(SEGV\_MAPERR)@0x0000000000000000 probably caused by NULL pointer dereference报错，其中之一的报错信息如下：

Generated by HiviewDFX@OpenHarmony
================================================================
Device info:HUAWEI Mate 60 Pro
Build info:ALN-AL00 5.0.0.150(SP8C00E150R4P30log)
Fingerprint:xxxxxxxxx
Module name:com.example.application
Version:2.8.5
VersionCode:30
PreInstalled:No
Foreground:No
Timestamp:2025-04-30 14:17:03.643
Pid:42378
Uid:20020210
Process name:com.example.application
Process life time:18446744073709405886s
Reason:Signal:SIGSEGV(SEGV\_MAPERR)@0x0000000000000007  probably caused by NULL pointer dereference
Fault thread info:
Tid:42378, Name:m.example.application
#00 pc 0000000000135dc8 /data/storage/el1/bundle/libs/arm64/libnet.so(91a0f067f914ed44654e1191fccc295e60882cb0)
#01 pc 0000000000135d68 /data/storage/el1/bundle/libs/arm64/libnet.so(91a0f067f914ed44654e1191fccc295e60882cb0)
#02 pc 00000000001397c0 /data/storage/el1/bundle/libs/arm64/libnet.so(91a0f067f914ed44654e1191fccc295e60882cb0)
#03 pc 000000000012b0d8 /data/storage/el1/bundle/libs/arm64/libnet.so(91a0f067f914ed44654e1191fccc295e60882cb0)
#04 pc 000000000012aa78 /data/storage/el1/bundle/libs/arm64/libnet.so(doCallback(napi\_env\_\_\*, napi\_status, void\*)+1584)(91a0f067f914ed44654e1191fccc295e60882cb0)
#05 pc 00000000000704f4 /system/lib64/platformsdk/libace\_napi.z.so(NativeSafeAsyncWork::ProcessAsyncHandle()+596)(85e70f1f5cf0e81468ec141fc2f4922c)
#06 pc 0000000000016de4 /system/lib64/platformsdk/libuv.so(uv\_\_async\_io+352)(81fe2b78ed1df8447a6c4e51c5f644e2)
#07 pc 0000000000028840 /system/lib64/platformsdk/libuv.so(uv\_\_io\_poll+1016)(81fe2b78ed1df8447a6c4e51c5f644e2)
#08 pc 00000000000173cc /system/lib64/platformsdk/libuv.so(uv\_run+408)(81fe2b78ed1df8447a6c4e51c5f644e2)
#09 pc 000000000007f250 /system/lib64/platformsdk/libruntime.z.so(OHOS::AbilityRuntime::OHOSLoopHandler::OnTriggered()+140)(17e438b05b67ccb9c7eb96e54ed833e5)
#10 pc 0000000000020430 /system/lib64/chipset-pub-sdk/libeventhandler.z.so(770d0cd78402a5ad1ced37fad50c5707)
#11 pc 000000000001bdb4 /system/lib64/chipset-pub-sdk/libeventhandler.z.so(OHOS::AppExecFwk::EventHandler::DistributeEvent(std::\_\_h::unique\_ptr<OHOS::AppExecFwk::InnerEvent, void (\*)(OHOS::AppExecFwk::InnerEvent\*)> const&)+1140)(770d0cd78402a5ad1ced37fad50c5707)

#### 背景知识

[CppCrash（进程崩溃）](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/cppcrash-guidelines)是指C/C++运行时崩溃。目前主要支持[崩溃异常信号](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/cppcrash-guidelines#系统处理的崩溃信号)SIGBUS、SIGFPE、SIGSEGV、SIGSTKFLT、SIGSYS、SIGILL、SIGTRAP、SIGABRT的处理。可以通过FaultLogger模块[获取崩溃日志](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/cppcrash-guidelines#日志获取)。

崩溃日志报错中空指针解引用NULL pointer dereference表现形式一般为：

*   形如SIGSEGV(SEGV\_MAPERR)@0x00000000或CppCrash日志的Register中打印的r0，r1等传参寄存器的值为0时，应首先考虑检查调用时是否传入了空指针。
*   形如SIGSEGV(SEGV\_MAPERR)@0x0000000c或CppCrash日志Register中打印的r1等传参寄存器的值为一个很小的值时应考虑检查调用入参的结构体成员是否包含空指针。

定位该类型问题一般尝试以下几种方法：

1.  使用DevEco Studio中链接应用，尝试直接点击崩溃日志中的调用栈跳转到对应行号。在应用开发场景，对于应用自身的动态库生成的CppCrash堆栈可直接跳转到代码行处，支持Native栈帧和ArkTS栈帧，无需开发者自行进行解析行号操作。
2.  对于未能解析跳转到对应行号的栈帧，可使用[llvm-addr2line工具解析](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-exception-stack-parsing-principle#section1735713501344)定位崩溃行号。注意在使用llvm-addr2line工具前需要[将release编译的so带上符号表](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-exception-stack-parsing-principle#section5147812132)，同时将build-profile.json5中[debugSymbol](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-hvigor-cpp#section2182144382320)的strip字段设置为"false"。
3.  使用[ASan检测](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-asan#section111599216114)内存错误。使用DevEco Studio集成的ASan（Address-Sanitizer）来检测面向C/C++的地址报错，并通过FaultLog展示的错误堆栈详情及导致错误的代码行来进行问题定位。
4.  结合业务检视代码。根据基于崩溃栈定位行号章节中介绍的三种方式获取到栈顶对应的行号后，回到代码中，检视上下文。

#### 问题定位

1.  由于出现问题的场景不明确，所以首先通过崩溃栈日志进行规律总结。经过查看多次的崩溃栈，发现基本都是在回调函数中出现的崩溃，比如以下的libnet.so中doCallback函数，于是怀疑问题出在各回调函数中的共性问题。
    
    pc 0000000000135dc8 /data/storage/el1/bundle/libs/arm64/libnet.so(91a0f067f914ed44654e1191fccc295e60882cb0)
    #01 pc 0000000000135d68 /data/storage/el1/bundle/libs/arm64/libnet.so(91a0f067f914ed44654e1191fccc295e60882cb0)
    #02 pc 00000000001397c0 /data/storage/el1/bundle/libs/arm64/libnet.so(91a0f067f914ed44654e1191fccc295e60882cb0)
    #03 pc 000000000012b0d8 /data/storage/el1/bundle/libs/arm64/libnet.so(91a0f067f914ed44654e1191fccc295e60882cb0)
    #04 pc 000000000012aa78 /data/storage/el1/bundle/libs/arm64/libnet.so(doCallback(napi\_env\_\_\*, napi\_status, void\*)+1584)(91a0f067f914ed44654e1191fccc295e60882cb0)
    
2.  以doCallback回调作为突破口，尝试通过添加空指针保护，发现还是会偶现该问题。于是怀疑是由于doCallback函数在执行过程中被释放了使用的指针内存资源。
    
    void doCallback(napi\_env env, napi\_status status, void \*data) {
        if (env == nullptr || data == nullptr) {
            LOGE("Invalid env or data");
            return;
        }
       _ // ..._
    }
    
3.  使用llvm-addr2line（或者[堆栈轨迹分析](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-release-app-stack-analysis)）对出现崩溃的libnet.so尝试解析出文件名和行号。
    
    *   首先将libnet模块的build-profile.json5里面buildOption/externalNativeOptions中配置参数："arguments": "-DCMAKE\_BUILD\_TYPE=RelWithDebInfo"。
        
        {
          "apiType": "stageMode",
          "buildOption": {
            "externalNativeOptions": {
              "path": "./src/main/cpp/CMakeLists.txt",
              "arguments": \["-DCMAKE\_BUILD\_TYPE=RelWithDebInfo"\],
              "cppFlags": "",
            }
          },
          _// ..._
        }
        
    
    *   然后将libnet模块的build-profile.json5里面buildOptionSet/nativeLib/debugSymbol/strip设置为"false"。（注意下方示例中的name为"debug"包，如需"release"包带上符号表则需要在"name"为"release"的构建配置中修改）。
        
        "buildOptionSet": \[
            {
              "name": "debug",
              "arkOptions": {
                "obfuscation": {
                  "ruleOptions": {
                    "enable": false,
                    "files": \[
                      "./obfuscation-rules.txt"
                    \]
                  }
                }
              },
              "nativeLib": {
                "debugSymbol": {
                  "strip": false,
                  "exclude": \[\]
                }
              }
            },
          \],
        
    
    *   编译出libnet.so后，确认是否已带上符号表：
        *   在Linux中可使用file libnet.so命令，查看最后是否有not stripped字段，带了则表示编译出的libnet.so带上了符号表。
            
            \[root@ncn4b-partnervectorservice-33-83-97 arm64-v8a\]# file libnet.so 
            libnet.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID\[sha1\]=9d075a569e007bc6e4ea25f2f96be548724b4aef, with debug\_info, not stripped
            
        *   在windows中可使用llvm-objdump --headers libnet.so（llvm-objdump工具在DevEco Studio安装的时候会自带），查看是否有debug字段，有则说明带上了符号表，没有则说明无符号表：
            
            ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/bc/v3/2YI7hVeTT5iIJEn9AuyhWw/zh-cn_image_0000002628554888.png?HW-CC-KV=V1&HW-CC-Date=20260709T133738Z&HW-CC-Expire=86400&HW-CC-Sign=B24DE5FE1CA28690FD7D773E843CEB913883D99E59E5D6F2B6F0E57A08525347 "点击放大")
            
    
    *   使用编译出来的带符号表的libnet.so使用llvm-addr2line进行崩溃行号定位：
        
        llvm-addr2line -Cipe LocalPath/libnet.so 000000000012aa78
        
    
    *   得到出问题的行信息，定位到崩溃在napi\_call\_function函数这行。
        
        napi\_call\_function(env, nullptr, callback, 1, &returnValue, &tempValue);
        
    
    说明是napi\_call\_function在调用ArkTS函数指针的时候，回调函数指针可能被其他线程释放了才导致的踩空。
    
4.  通过代码分析发现问题所在ArkTS层往Native层传递函数参数的时候，需要依赖的回调函数指针必须是有效的。
    
    但是从上层传下来的函数制造者却没有创建强引用napi\_ref保留。所以当GC回收了ArkTS的回调函数资源后，使用该ArkTS回调函数可能在Native执行napi\_call\_function前就已经是空指针了，最后导致空指针解引用。
    

#### 分析结论

*   使用napi\_call\_function函数调用ArkTS层函数前，要使用napi\_create\_reference创建一个强引用napi\_ref，防止GC回收ArkTS的回调函数资源。
*   然后通过napi\_get\_reference\_value从napi\_ref中提取当前有效的napi\_value。此时napi\_value就是持久化后的ArkTS层的持久化的函数指针，这个时候使用napi\_call\_function函数调用改指针才是安全的。
*   在使用完后需要调用napi\_delete\_reference主动释放引用，避免内存泄漏。

#### 修改建议

*   在Native层中，首先在获取异步回调ArkTS层函数指针的时候，需要使用napi\_create\_reference创建强引用将指针缓存起来，在使用结束后，需要调用napi\_delete\_reference释放强引用，避免资源泄露。示例代码如下：
    
    _// 异步工作Native流程_
    static napi\_value StartAsyncWork(napi\_env env, napi\_callback\_info info)
    {
        _// 从模块数据中获取函数引用_
        ModuleData\* moduleData = nullptr;
        napi\_get\_instance\_data(env, (void\*\*)&moduleData);
    
        if (moduleData == nullptr || moduleData->arktsFuncRef == nullptr) {
            napi\_throw\_error(env, nullptr, "请先注册ArkTS函数");
            return nullptr;
        }
    
      _  // 创建新的工作数据_
        AsyncWorkData\* workData = new AsyncWorkData();
        workData->env = env;
    
       _ // 为异步工作创建新的函数引用_
        napi\_value arktsFunc;
        if (napi\_get\_reference\_value(env, moduleData->arktsFuncRef, &arktsFunc) != napi\_ok) {
            delete workData;
            napi\_throw\_error(env, nullptr, "获取注册的函数失败");
            return nullptr;
        }
    
      _  // 创建新的引用给异步工作使用_
        if (napi\_create\_reference(env, arktsFunc, 1, &workData->arktsFuncRef) != napi\_ok) {
            delete workData;
            napi\_throw\_error(env, nullptr, "为异步工作创建函数引用失败");
            return nullptr;
        }
    
        _// 创建异步工作_
        napi\_async\_work asyncWork;
        napi\_value workName;
        napi\_create\_string\_utf8(env, "MyProc", NAPI\_AUTO\_LENGTH, &workName);
    
        if (napi\_create\_async\_work(env, nullptr, workName, ExecuteWork, doCallback, workData, &asyncWork) != napi\_ok) {
            napi\_delete\_reference(env, workData->arktsFuncRef);
            delete workData;
            napi\_throw\_error(env, nullptr, "创建异步工作失败");
            return nullptr;
        }
    
       _ // 排队执行异步工作_
        if (napi\_queue\_async\_work(env, asyncWork) != napi\_ok) {
            napi\_delete\_async\_work(env, asyncWork);
            napi\_delete\_reference(env, workData->arktsFuncRef);
            delete workData;
            napi\_throw\_error(env, nullptr, "排队异步工作失败");
            return nullptr;
        }
    
        OH\_LOG\_INFO(LOG\_APP, "异步工作已启动");
    
        napi\_value result;
        napi\_get\_undefined(env, &result);
        return result;
    }
    
*   在执行完数据的处理后，napi\_create\_async\_work函数会回调doCallback函数，在该函数中，在使用napi\_call\_function函数调用ArkTS层函数指针前，使用napi\_get\_reference\_value获取缓存中的ArkTS函数指针。示例代码如下：
    
    _// 异步工作完成回调（在主线程/JS线程中执行）_
    void doCallback(napi\_env env, napi\_status status, void\* data)
    {
        AsyncWorkData\* workData = static\_cast<AsyncWorkData\*>(data);
    
        if (status != napi\_ok || workData == nullptr) {
            OH\_LOG\_ERROR(LOG\_APP, "异步工作完成回调出错");
            return;
        }
    
     _   // 安全地调用ArkTS函数_
        if (workData->arktsFuncRef != nullptr) {
            napi\_handle\_scope scope;
            napi\_status status;
    
           _ // 创建作用域_
            if (napi\_open\_handle\_scope(env, &scope) != napi\_ok) {
                OH\_LOG\_ERROR(LOG\_APP, "打开handle scope失败");
              _  // 清理工作数据_
                if (workData->arktsFuncRef != nullptr) {
                    napi\_delete\_reference(env, workData->arktsFuncRef);
                }
                delete workData;
                return;
            }
    
            napi\_value arktsFunc;
            status = napi\_get\_reference\_value(env, workData->arktsFuncRef, &arktsFunc);
            if (status == napi\_ok && arktsFunc != nullptr) {
              _  // 创建要传递给ArkTS函数的参数，本例为字符串_
                napi\_value argv\[1\];
                napi\_create\_string\_utf8(env, workData->resultMessage.c\_str(), NAPI\_AUTO\_LENGTH, &argv\[0\]);
               _ // 调用ArkTS函数_
                napi\_value global;
                napi\_get\_global(env, &global);
    
                napi\_value result;
                if (napi\_call\_function(env, global, arktsFunc, 1, argv, &result) == napi\_ok) {
                    OH\_LOG\_INFO(LOG\_APP, "成功调用ArkTS回调函数，消息: %{public}s", 
                               workData->resultMessage.c\_str());
                } else {
                    OH\_LOG\_ERROR(LOG\_APP, "调用ArkTS函数失败");
                }
            } else {
                OH\_LOG\_ERROR(LOG\_APP, "获取ArkTS函数引用失败");
            }
          _  // 关闭作用域_
            napi\_close\_handle\_scope(env, scope);
        }
    }
    

完整示例参考如下：

*   entry/src/main/cpp/CMakeLists.txt：
    
    _\# the minimum version of CMake._
    cmake\_minimum\_required(VERSION 3.5.0)
    project(SQI202505101216105442012)
    
    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 napi\_init.cpp)
    target\_link\_libraries(entry PUBLIC libace\_napi.z.so libhilog\_ndk.z.so libuv.so)
    
*   entry/src/main/cpp/napi\_init.cpp：
    
    _/\*_
     _\* Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved._
     _\*/_
    
    #include "napi/native\_api.h"
    #include <thread>
    #include "hilog/log.h"
    #include <uv.h>
    
    #undef LOG\_DOMAIN
    #undef LOG\_TAG
    #define LOG\_DOMAIN 0x3200  _// 全局domain宏，标识业务领域_
    #define LOG\_TAG "MY\_TAG"  _ // 全局tag宏，标识模块日志tag_
    
    _// 异步工作数据结构_
    struct AsyncWorkData {
        napi\_env env = nullptr;
        napi\_ref arktsFuncRef = nullptr;  _// 保存ArkTS函数的引用_
        std::string resultMessage;       _ // 要传递给ArkTS的结果_
    };
    
    _// 模块全局数据_
    struct ModuleData {
        napi\_ref arktsFuncRef = nullptr;
    };
    
    _// 异步工作执行函数（在工作线程中执行）_
    void ExecuteWork(napi\_env env, void\* data)
    {
        AsyncWorkData\* workData = static\_cast<AsyncWorkData\*>(data);
    
       _ // 模拟一些耗时操作_
        for (int i = 0; i < 3; i++) {
            OH\_LOG\_INFO(LOG\_APP, "耗时异步流程执行中... %{public}d", i);
           _ // 模拟工作耗时操作_
            std::this\_thread::sleep\_for(std::chrono::milliseconds(500));
        }
    
       _ // 准备要传递给ArkTS的消息_
        workData->resultMessage = "来自Native层的异步完成消息，时间戳: " + 
                                 std::to\_string(uv\_hrtime() / 1000000);
    }
    
    _// 异步工作完成回调（在主线程/JS线程中执行）_
    void doCallback(napi\_env env, napi\_status status, void\* data)
    {
        AsyncWorkData\* workData = static\_cast<AsyncWorkData\*>(data);
    
        if (status != napi\_ok || workData == nullptr) {
            OH\_LOG\_ERROR(LOG\_APP, "异步工作完成回调出错");
            return;
        }
    
       _ // 安全地调用ArkTS函数_
        if (workData->arktsFuncRef != nullptr) {
            napi\_handle\_scope scope;
            napi\_status status;
    
         _   // 创建作用域_
            if (napi\_open\_handle\_scope(env, &scope) != napi\_ok) {
                OH\_LOG\_ERROR(LOG\_APP, "打开handle scope失败");
               _ // 清理工作数据_
                if (workData->arktsFuncRef != nullptr) {
                    napi\_delete\_reference(env, workData->arktsFuncRef);
                }
                delete workData;
                return;
            }
    
            napi\_value arktsFunc;
            status = napi\_get\_reference\_value(env, workData->arktsFuncRef, &arktsFunc);
            if (status == napi\_ok && arktsFunc != nullptr) {
               _ // 创建要传递给ArkTS函数的参数，本例为字符串_
                napi\_value argv\[1\];
                napi\_create\_string\_utf8(env, workData->resultMessage.c\_str(), NAPI\_AUTO\_LENGTH, &argv\[0\]);
                _// 调用ArkTS函数_
                napi\_value global;
                napi\_get\_global(env, &global);
    
                napi\_value result;
                if (napi\_call\_function(env, global, arktsFunc, 1, argv, &result) == napi\_ok) {
                    OH\_LOG\_INFO(LOG\_APP, "成功调用ArkTS回调函数，消息: %{public}s", 
                               workData->resultMessage.c\_str());
                } else {
                    OH\_LOG\_ERROR(LOG\_APP, "调用ArkTS函数失败");
                }
            } else {
                OH\_LOG\_ERROR(LOG\_APP, "获取ArkTS函数引用失败");
            }
          _  // 关闭作用域_
            napi\_close\_handle\_scope(env, scope);
        }
    }
    
    _// 注册ArkTS函数的Native方法_
    static napi\_value RegisterArkTSFunction(napi\_env env, napi\_callback\_info info)
    {
        size\_t argc = 1;
        napi\_value args\[1\];
        napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
    
        if (argc < 1) {
            napi\_throw\_error(env, nullptr, "需要传入ArkTS函数作为参数");
            return nullptr;
        }
    
        napi\_valuetype valuetype;
        napi\_typeof(env, args\[0\], &valuetype);
        if (valuetype != napi\_function) {
            napi\_throw\_type\_error(env, nullptr, "参数必须是一个函数");
            return nullptr;
        }
    
      _  // 获取模块数据_
        ModuleData\* moduleData = nullptr;
        napi\_get\_instance\_data(env, (void\*\*)&moduleData);
        if (moduleData == nullptr) {
            moduleData = new ModuleData();
            napi\_set\_instance\_data(env, moduleData, \[\](napi\_env env, void\* data, void\* hint) {
                ModuleData\* moduleData = static\_cast<ModuleData\*>(data);
                if (moduleData && moduleData->arktsFuncRef) {
                    napi\_delete\_reference(env, moduleData->arktsFuncRef);
                }
                delete moduleData;
            }, nullptr);
        } else {
          _  // 如果已经注册过函数，先清理旧的引用_
            if (moduleData->arktsFuncRef != nullptr) {
                napi\_delete\_reference(env, moduleData->arktsFuncRef);
                moduleData->arktsFuncRef = nullptr;
            }
        }
    
       _ // 创建对ArkTS函数的强引用，防止被GC_
        napi\_status status = napi\_create\_reference(env, args\[0\], 1, &moduleData->arktsFuncRef);
        if (status != napi\_ok) {
            napi\_throw\_error(env, nullptr, "创建函数引用失败");
            return nullptr;
        }
    
        OH\_LOG\_INFO(LOG\_APP, "ArkTS函数注册成功");
    
        napi\_value result;
        napi\_get\_undefined(env, &result);
        return result;
    }
    
    _// 异步工作Native流程_
    static napi\_value StartAsyncWork(napi\_env env, napi\_callback\_info info)
    {
       _ // 从模块数据中获取函数引用_
        ModuleData\* moduleData = nullptr;
        napi\_get\_instance\_data(env, (void\*\*)&moduleData);
    
        if (moduleData == nullptr || moduleData->arktsFuncRef == nullptr) {
            napi\_throw\_error(env, nullptr, "请先注册ArkTS函数");
            return nullptr;
        }
    
      _  // 创建新的工作数据_
        AsyncWorkData\* workData = new AsyncWorkData();
        workData->env = env;
    
       _ // 为异步工作创建新的函数引用_
        napi\_value arktsFunc;
        if (napi\_get\_reference\_value(env, moduleData->arktsFuncRef, &arktsFunc) != napi\_ok) {
            delete workData;
            napi\_throw\_error(env, nullptr, "获取注册的函数失败");
            return nullptr;
        }
    
       _ // 创建新的引用给异步工作使用_
        if (napi\_create\_reference(env, arktsFunc, 1, &workData->arktsFuncRef) != napi\_ok) {
            delete workData;
            napi\_throw\_error(env, nullptr, "为异步工作创建函数引用失败");
            return nullptr;
        }
    
       _ // 创建异步工作_
        napi\_async\_work asyncWork;
        napi\_value workName;
        napi\_create\_string\_utf8(env, "MyProc", NAPI\_AUTO\_LENGTH, &workName);
    
        if (napi\_create\_async\_work(env, nullptr, workName, ExecuteWork, doCallback, workData, &asyncWork) != napi\_ok) {
            napi\_delete\_reference(env, workData->arktsFuncRef);
            delete workData;
            napi\_throw\_error(env, nullptr, "创建异步工作失败");
            return nullptr;
        }
    
       _ // 排队执行异步工作_
        if (napi\_queue\_async\_work(env, asyncWork) != napi\_ok) {
            napi\_delete\_async\_work(env, asyncWork);
            napi\_delete\_reference(env, workData->arktsFuncRef);
            delete workData;
            napi\_throw\_error(env, nullptr, "排队异步工作失败");
            return nullptr;
        }
    
        OH\_LOG\_INFO(LOG\_APP, "异步工作已启动");
    
        napi\_value result;
        napi\_get\_undefined(env, &result);
        return result;
    }
    
    EXTERN\_C\_START
    static napi\_value Init(napi\_env env, napi\_value exports)
    {
        napi\_property\_descriptor desc\[\] = {
            { "registerArkTSFunction", nullptr, RegisterArkTSFunction, nullptr, nullptr, nullptr, napi\_default, nullptr },
            { "startAsyncWork", nullptr, StartAsyncWork, 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);
    }
    
*   entry/src/main/cpp/types/libentry/Index.d.ts：
    
    export const registerArkTSFunction: (callback: (message: string) => void) => void;
    export const startAsyncWork: () => void;
    
*   entry/src/main/ets/pages/Index.ets：
    
    import testNapi from 'libentry.so';
    
    _// 要传递给Native层的回调函数_
    function myArkTSFunction(message: string): void {
      console.info('ArkTS收到Native消息: ' + message);
    }
    
    @Entry
    @Component
    struct Index {
      @State message: string = 'Hello World';
    
      aboutToAppear(): void {
        this.registerCallbackToNative();
      }
    
      build() {
        Row() {
          Column() {
            Text(this.message)
              .fontSize(20)
              .margin(10)
    
            Button('触发异步工作')
              .onClick(() => {
                this.triggerAsyncWork();
                this.message = '异步工作已触发';
              })
              .margin(10)
          }
          .width('100%');
        }
        .height('100%');
      }
    
     _ // 注册回调函数到Native层_
      registerCallbackToNative(): void {
        try {
          testNapi.registerArkTSFunction(myArkTSFunction);
          console.info('ArkTS函数注册成功');
        } catch (error) {
          console.error('注册ArkTS函数失败: ' + error);
        }
      }
    
     _ // 触发Native层的异步工作_
      triggerAsyncWork(): void {
        try {
          testNapi.startAsyncWork();
          console.info('已触发Native异步工作');
        } catch (error) {
          console.error('触发异步工作失败: ' + error);
        }
      }
    }