C++ Turbo Native Modules
这个文档仍然是实验性的,随着我们的迭代,细节会有变化。欢迎在工作小组内的讨论中分享你的反馈。
此外,它还包含几个手动步骤。请注意新架构尚未稳定下来,最终的开发者体验会继续迭代改善。我们正在努力开发工具、模板和库,以帮助你在新架构上快速入门,而不需要经历整个设置过程。
This guide shows you how to implement a Turbo Native Module using C++ only, a way to share the same implementation with any supported platform (Android, iOS, macOS or Windows).
Before continuing with this guide, please read the Turbo Native Modules section. As a further reference, we prepared an example for the RNTester app (NativeCxxModuleExample) and a sample run in our community repository (run/pure-cxx-module).
C++ Turbo Native Modules work with the New Architecture enabled. To migrate to the New Architecture, follow the Migration guide
How to Create a C++ Turbo Native Module
To create a C++ Turbo Native Module, you need to:
- Define the JavaScript specification.
- Configure Codegen to generate the scaffolding.
- Register the native module.
- Write the native code to finish implementing the module.
Setup a Test App for the New Architecture
As first step, create a new application:
npx react-native@v0.71.0-rc.3 init CxxTurboModulesGuide --version v0.71.0-rc.3
cd CxxTurboModulesGuide
yarn install
On Android enable the New Architecture by modifying the android/gradle.properties
file:
- newArchEnabled=false
+ newArchEnabled=true
On iOS enable the New Architecture when running pod install
in the ios
folder:
RCT_NEW_ARCH_ENABLED=1 bundle exec pod install
Turbo Module Folder Setup
Create a tm
folder inside the project. It will contain all C++ TurboModules of your application. The final result should look like this:
CxxTurboModulesGuide
├── android
├── ios
├── js
└── tm
1. JavaScript Specification
Create the following spec inside the tm
folder:
- typescript
- flow
import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport';
// import type {TurboModule} from 'react-native'; in future versions
import {TurboModuleRegistry} from 'react-native';
export interface Spec extends TurboModule {
readonly reverseString: (input: string) => string;
}
export default TurboModuleRegistry.getEnforcing<Spec>(
'NativeSampleModule',
);
// @flow
import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport';
// import type {TurboModule} from 'react-native'; in future versions
import {TurboModuleRegistry} from 'react-native';
export interface Spec extends TurboModule {
+reverseString: (input: string) => string;
}
export default (TurboModuleRegistry.getEnforcing<Spec>(
'NativeSampleModule',
): Spec);
2. Codegen Configuration
Next, you need to add some configuration for Codegen.
Application
Update your app's package.json
file with the following entries:
{
// ...
"description": "React Native with Cxx Turbo Native Modules",
"author": "<Your Name> <your_email@your_provider.com> (https://github.com/<your_github_handle>)",
"license": "MIT",
"homepage": "https://github.com/<your_github_handle>/#readme",
// ...
"codegenConfig": {
"name": "AppSpecs",
"type": "all",
"jsSrcsDir": "tm",
"android": {
"javaPackageName": "com.facebook.fbreact.specs"
}
}
}
It adds necessary properties which we will later re-use in the iOS podspec
file and configures Codegen to search for specs inside the tm
folder.
C++ Turbo Native Modules don't autolink and need to be manually included into the app with the described steps below.
iOS: Create the podspec
file
For iOS, you'll need to create a AppTurboModules.podspec
file in the tm
folder - which will look like:
require "json"
package = JSON.parse(File.read(File.join(__dir__, "../package.json")))
Pod::Spec.new do |s|
s.name = "AppTurboModules"
s.version = package["version"]
s.summary = package["description"]
s.description = package["description"]
s.homepage = package["homepage"]
s.license = package["license"]
s.platforms = { :ios => "12.4" }
s.author = package["author"]
s.source = { :git => package["repository"], :tag => "#{s.version}" }
s.source_files = "**/*.{h,cpp}"
s.pod_target_xcconfig = {
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
}
install_modules_dependencies(s)
end
You need to add it as a dependency to your application in ios/Podfile
, e.g., after the use_react_native!(...)
section:
if ENV['RCT_NEW_ARCH_ENABLED'] == '1'
pod 'AppTurboModules', :path => "./../tm"
end
Android: build.gradle
, CMakeLists.txt
, Onload.cpp
For Android, you'll need to create a CMakeLists.txt
file in the tm
folder - which will look like:
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE on)
add_compile_options(
-fexceptions
-frtti
-std=c++17)
file(GLOB tm_SRC CONFIGURE_DEPENDS *.cpp)
add_library(tm STATIC ${tm_SRC})
target_include_directories(tm PUBLIC .)
target_include_directories(react_codegen_AppSpecs PUBLIC .)
target_link_libraries(tm
jsi
react_nativemodule_core
react_codegen_AppSpecs)
It defines the tm
folder as a source for native code and sets up necessary dependencies.
You need to add it as a dependency to your application in android/app/build.gradle
, e.g., at the very end of that file:
android {
externalNativeBuild {
cmake {
path "src/main/jni/CMakeLists.txt"
}
}
}
Ensure to pick the correct android/app/build.gradle file and not android/build.gradle.