准备环境
- volta
$ volta ls
⚡️ Currently active tools:
Node: v16.20.2 (default)
Yarn: v1.22.19 (default)
Tool binaries available:
nrm (default)
- nrm
$ nrm ls
* npm ---------- https://registry.npmjs.org/
yarn --------- https://registry.yarnpkg.com/
tencent ------ https://mirrors.cloud.tencent.com/npm/
cnpm --------- https://r.cnpmjs.org/
taobao ------- https://registry.npmmirror.com/
npmMirror ---- https://skimdb.npmjs.com/registry/
- react-native
$ npx react-native info
...
react-native:
installed: 0.72.6
...
- create-react-native-library
$ npx create-react-native-library --version
0.34.2
创建my-mod
- 创建my-mod
$ npx create-react-native-library my-mod
✔ What is the name of the npm package? … react-native-my-mod
✔ What is the description for the package? … My module with C++
✔ What is the name of package author? … Sunbreak
✔ What is the email address for the package author? … sunbreak.wang@gmail.com
✔ What is the URL for the package author? … https://github.com/Sunbreak
✔ What is the URL for the repository? … https://github.com/Sunbreak/react-native-my-mod
✔ What type of library do you want to develop? › Native module
✔ Which languages do you want to use? › C++ for Android & iOS
✔ Project created successfully at my-mod!
- 初始化my-mod
$ cd my-mod
$ yarn
- Android运行my-mod
$ yarn example start &
$ yarn example android
- iOS运行my-mode
$ yarn example start &
$ yarn example ios
适配JSI
适配JS/TS
- 修改index.tsx
export function multiply(a: number, b: number): number {
return global.multiply(a, b);
}
- 修改App.tsx
-export default function App() {
- const [result, setResult] = React.useState<number | undefined>();
+const result = multiply(3, 7);
- React.useEffect(() => {
- multiply(3, 7).then(setResult);
- }, []);
+export default function App() {
适配C++
- 修改react-native-my-mod.h
#ifndef MYMOD_H
#define MYMOD_H
+#include "jsi/jsi.h"
+
namespace mymod {
- double multiply(double a, double b);
+
+void install(facebook::jsi::Runtime &runtime);
+
}
#endif /* MYMOD_H */
- 修改react-native-my-mod.cpp
#include "react-native-my-mod.h"
using namespace facebook::jsi;
namespace mymod {
void install(Runtime &runtime) {
runtime.global().setProperty(
runtime,
"multiply",
Function::createFromHostFunction(
runtime,
PropNameID::forAscii(runtime, "multiply"),
2,
[](Runtime &rt, const Value &thisVal, const Value *args, size_t count) -> Value {
double a = args[0].getNumber();
double b = args[1].getNumber();
return { a * b };
}
)
);
}
}
适配Android
- 修改build.gradle
defaultConfig {
...
externalNativeBuild {
cmake {
+ arguments "-DANDROID_STL=c++_shared"
cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all"
abiFilters "x86", "x86_64", "armeabi-v7a", "arm64-v8a"
}
}
}
+ packagingOptions {
+ exclude "**/libjsi.so"
+ }
+
+ buildFeatures {
+ prefab true
+ }
- 修改CMakelists.txt
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_STANDARD 17)
# Define the library name here.
project(cpp)
find_package(ReactAndroid REQUIRED CONFIG)
add_library(${CMAKE_PROJECT_NAME}
SHARED
../cpp/react-native-my-mod.cpp
cpp-adapter.cpp
)
# Specifies a path to native header files.
target_include_directories(${CMAKE_PROJECT_NAME}
PRIVATE
../cpp
)
target_link_libraries(${CMAKE_PROJECT_NAME}
ReactAndroid::jsi
)
- 修改cpp-adapter.cpp
#include "react-native-my-mod.h"
extern "C"
-JNIEXPORT jdouble JNICALL
-Java_com_mymod_MyModModule_nativeMultiply(JNIEnv *env, jclass type, jdouble a, jdouble b) {
- return mymod::multiply(a, b);
+JNIEXPORT void JNICALL
+Java_com_mymod_MyModModule_nativeInstall(JNIEnv *env, jclass type, jlong jsContext) {
+ auto runtime = reinterpret_cast<facebook::jsi::Runtime *>(jsContext);
+ mymod::install(*runtime);
}
- 修改MyModModule.java
- private static native double nativeMultiply(double a, double b);
-
- // Example method
- // See https://reactnative.dev/docs/native-modules-android
- @ReactMethod
- public void multiply(double a, double b, Promise promise) {
- promise.resolve(nativeMultiply(a, b));
- }
+ public static native void nativeInstall(long jsContext);
- 修改example/android中的MainApplication.java
protected Boolean isHermesEnabled() {
return BuildConfig.IS_HERMES_ENABLED;
}
+
+ @Override
+ protected JSIModulePackage getJSIModulePackage() {
+ JSIModulePackage jsiModulePackage = super.getJSIModulePackage();
+ return (reactApplicationContext, javaScriptContextHolder) -> {
+ reactApplicationContext.getNativeModule(MyModModule.class).nativeInstall(javaScriptContextHolder.get());
+ if (jsiModulePackage != null) {
+ return jsiModulePackage.getJSIModules(reactApplicationContext, javaScriptContextHolder);
+ }
+ return new ArrayList<>();
+ };
+ }
};
适配iOS
- 修改MyMod.h
-#ifdef RCT_NEW_ARCH_ENABLED
-#import "RNMyModSpec.h"
-
-@interface MyMod : NSObject <NativeMyModSpec>
-#else
#import <React/RCTBridgeModule.h>
@interface MyMod : NSObject <RCTBridgeModule>
-#endif
- 修改MyMod.mm
#import "MyMod.h"
#import "jsi/jsi.h"
#import <React/RCTBridge+Private.h>
using namespace facebook::jsi;
@implementation MyMod
@synthesize bridge = _bridge;
RCT_EXPORT_MODULE()
+ (BOOL)requiresMainQueueSetup {
return YES;
}
- (void)setBridge:(RCTBridge *)bridge {
_bridge = bridge;
RCTCxxBridge *cxxBridge = (RCTCxxBridge *)bridge;
Runtime &runtime = *(Runtime *)cxxBridge.runtime;
mymod::install(runtime);
}
@end
测试适配结果
参考“创建my-mod”