React Native跨平台鸿蒙开发高级应用原理:如何创建 C++ Turbo 原生模块,形成胶水代码文件
本文介绍了在OpenHarmony平台上开发原生模块的具体实现方法。主要内容包括:1) 创建CalculatorModule.ts实现基础计算功能;2) 构建GeneratedPackage.ets文件并重写必要方法;3) 针对CxxTurboModule的特殊处理方式,包括修改RTNCalculator.cpp中的方法实现;4) 在CMakeLists.txt中添加胶水代码文件路径。文档详细说明
编写原生代码
-
创建用于实现模块的
CalculatorModule.ts。在
entry/src/main/ets路径下新建文件夹turbomodule,并在文件夹中新增CalculatorModule.ts。
如果是 ArkTSTurboModule,需要在此处实现:// entry/src/main/ets/turbomodule/CalculatorModule.ts import { AnyThreadTurboModule, UITurboModule } from '@rnoh/react-native-openharmony/ts'; import { TM } from '@rnoh/react-native-openharmony/generated/ts'; export class CalculatorModule extends UITurboModule implements TM.RTNCalculator.Spec { add(a: number, b: number): Promise<number>{ return Promise.resolve(a+b); } }如果是 cxxTurboModule,不需要在此处实现,只需保证函数的参数类型和返回类型正确即可:
// entry/src/main/ets/turbomodule/CalculatorModule.ts import { AnyThreadTurboModule, UITurboModule } from '@rnoh/react-native-openharmony/ts'; import { TM } from '@rnoh/react-native-openharmony/generated/ts'; export class CalculatorModule extends UITurboModule implements TM.RTNCalculator.Spec { add(a: number, b: number): Promise<number>{ return Promise.resolve(123456); } } -
创建 Package 的实现文件
GeneratedPackage.ets。在
entry/src/main/ets路径下新建GeneratedPackage.ets,并添加对应的实现代码:// entry/src/main/ets/GeneratedPackage.ets import { RNOHPackage, AnyThreadTurboModule, AnyThreadTurboModuleContext, UITurboModule, UITurboModuleContext } from '@rnoh/react-native-openharmony'; import { TM } from "@rnoh/react-native-openharmony/generated" import { CalculatorModule } from './turbomodule/CalculatorModule'; export default class GeneratedPackage extends RNOHPackage { override getUITurboModuleFactoryByNameMap(): Map<string, (ctx: UITurboModuleContext) => UITurboModule | null> { return new Map<string, ((ctx: UITurboModuleContext) => UITurboModule)>() .set(TM.RTNCalculator.NAME, (ctx) => new CalculatorModule(ctx)) } override async createEagerUITurboModuleByNameMap(ctx: UITurboModuleContext): Promise<Map<string, UITurboModule>> { const calculatorModule = new CalculatorModule(ctx); return new Map() .set(TM.RTNCalculator.NAME, calculatorModule) } }需要注意的是:
- 文件中应该使用
export default导出一个继承了RNOHPackage的类 - 重写父类方法
getUITurboModuleFactoryByNameMap()和createEagerUITurboModuleByNameMap() - 在
entry/src/main/ets/RNPackagesFactory.ets中添加创建该 Package 的方法:import { RNOHPackage, RNPackageContext } from '@rnoh/react-native-openharmony'; import GeneratedPackage from './GeneratedPackage'; export function createRNPackages(ctx: RNPackageContext): RNOHPackage[] { return [ new GeneratedPackage(ctx) ]; }
- 文件中应该使用
-
如果是 CxxTurboModule,需要一些额外步骤:
什么是:CxxTurboModule,请参考React Native 中文网。
以 CalculatorModule 为例,展开胶水代码文件
RTNCalculator.cpp中的宏 ARK_ASYNC_METHOD_METADATA:#include "RTNCalculator.h" namespace rnoh { using namespace facebook; RTNCalculator::RTNCalculator(const ArkTSTurboModule::Context ctx, const std::string name) : ArkTSTurboModule(ctx, name) { methodMap_ = { - ARK_ASYNC_METHOD_METADATA(add, 2), + { "add", + { 2, + [] (facebook::jsi::Runtime& rt, facebook::react::TurboModule& turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast<ArkTSTurboModule&>(turboModule).callAsync(rt, "add", args, count); + } + } + } }; } } // namespace rnoh删除 lambda 表达式中对 ArkTSTurboModule 的异步桥接调用,改为直接实现。
#include "RTNCalculator.h" namespace rnoh { using namespace facebook; RTNCalculator::RTNCalculator(const ArkTSTurboModule::Context ctx, const std::string name) : ArkTSTurboModule(ctx, name) { methodMap_ = { { "add", { 2, [] (facebook::jsi::Runtime& rt, facebook::react::TurboModule& turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast<ArkTSTurboModule&>(turboModule).callAsync(rt, "add", args, count); + return jsi::Value(args[0].asNumber() + args[1].asNumber()); } } } }; } } // namespace rnoh -
添加胶水代码。根据您所使用的 Codegen 版本不同,有2种操作方式:
v1版本
-
在
CMakeLists.txt中添加新增的胶水代码文件在
entry/src/main/cpp/CMakeLists.txt中定义 cpp 的 generated 路径,并添加到编译构建中:project(rnapp) cmake_minimum_required(VERSION 3.4.1) set(CMAKE_SKIP_BUILD_RPATH TRUE) set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules") set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}") set(RNOH_CPP_DIR "${OH_MODULE_DIR}/@rnoh/react-native-openharmony/src/main/cpp") set(RNOH_GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/generated") set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments") set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie") add_compile_definitions(WITH_HITRACE_SYSTRACE) set(WITH_HITRACE_SYSTRACE 1) # for other CMakeLists.txt files to use add_subdirectory("${RNOH_CPP_DIR}" ./rn) # RNOH_BEGIN: add_package_subdirectories add_subdirectory("${OH_MODULE_DIR}/@rnoh/sample-package/src/main/cpp" ./sample-package) # RNOH_END: add_package_subdirectories + file(GLOB GENERATED_CPP_FILES "./generated/*.cpp") add_library(rnoh_app SHARED + ${GENERATED_CPP_FILES} "./PackageProvider.cpp" "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp" ) target_link_libraries(rnoh_app PUBLIC rnoh) # RNOH_BEGIN: link_packages target_link_libraries(rnoh_app PUBLIC rnoh_sample_package) # RNOH_END: link_packages -
在
entry/src/main/cpp/PackageProvider.cpp中创建 cpp 侧的 package 对象:#include "RNOH/PackageProvider.h" #include "SamplePackage.h" + #include "generated/RNOHGeneratedPackage.h" using namespace rnoh; std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) { return { + std::make_shared<RNOHGeneratedPackage>(ctx), std::make_shared<SamplePackage>(ctx) }; }
v2版本
-
在
CMakeLists.txt中添加新增的胶水代码文件在这一步,需要在 CMake 文件中把 Codegen 生成的文件分别使用
add_library和target_include_directories添加到编译构建的任务中:project(rnapp) cmake_minimum_required(VERSION 3.4.1) set(CMAKE_SKIP_BUILD_RPATH TRUE) set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules") set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}") set(RNOH_CPP_DIR "${OH_MODULE_DIR}/@rnoh/react-native-openharmony/src/main/cpp") + set(RNOH_GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/generated") set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments") set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie") add_compile_definitions(WITH_HITRACE_SYSTRACE) set(WITH_HITRACE_SYSTRACE 1) # for other CMakeLists.txt files to use add_subdirectory("${RNOH_CPP_DIR}" ./rn) # RNOH_BEGIN: add_package_subdirectories add_subdirectory("${OH_MODULE_DIR}/@rnoh/sample-package/src/main/cpp" ./sample-package) # RNOH_END: add_package_subdirectories + set(rtn_calculator_generated_dir "${RNOH_GENERATED_DIR}/rtn_calculator") + file(GLOB_RECURSE rtn_calculator_generated_dir_SRC "${rtn_calculator_generated_dir}/**/*.cpp") + file(GLOB rtn_calculator_package_SRC CONFIGURE_DEPENDS *.cpp) add_library(rnoh_app SHARED + ${rtn_calculator_generated_dir_SRC} + ${rtn_calculator_package_SRC} "./PackageProvider.cpp" "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp" ) + target_include_directories(rnoh_app PUBLIC ${rtn_calculator_generated_dir}) target_link_libraries(rnoh_app PUBLIC rnoh) # RNOH_BEGIN: link_packages target_link_libraries(rnoh_app PUBLIC rnoh_sample_package) # RNOH_END: link_packages -
在
entry/src/main/cpp/PackageProvider.cpp中创建 cpp 侧的 package 对象:#include "RNOH/PackageProvider.h" #include "SamplePackage.h" + #include "generated/rtn_calculator/RNOH/generated/BaseRtnCalculatorPackage.h" using namespace rnoh; std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) { return { std::make_shared<SamplePackage>(ctx), + std::make_shared<BaseRtnCalculatorPackage>(ctx) }; }
打包
接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。

打包之后再将打包后的鸿蒙OpenHarmony文件拷贝到鸿蒙的DevEco-Studio工程目录去:

最后运行效果图如下显示:

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。
更多推荐
所有评论(0)