NativeModules导入
import { NativeModules } from 'react-native';
//调用方式
NativeModules.MyButton.xxx()
我们看看NativeModules是什么
//NativeModules.js
let NativeModules: {[moduleName: string]: $FlowFixMe, ...} = {};
if (global.nativeModuleProxy) {
NativeModules = global.nativeModuleProxy;
} else {
...
}
module.exports = NativeModules;
global.nativeModuleProxy是在JSIExecutor的initializeRuntime中初始化注入的
//JSIExecutor.cpp
void JSIExecutor::initializeRuntime() {
runtime_->global().setProperty(
*runtime_,
"nativeModuleProxy" ,
Object::createFromHostObject(
*runtime_, std::make_shared<NativeModuleProxy>(nativeModules_)));
...
}
当调用NativeModules.NativeModuleDemo时触发C++的NativeModuleProxy.get方法
- nativeModules_在前面分析过,它是JSINativeModules对象,里面包含ModuleRegistry对象
- nativeModules = nativeModules_
class JSIExecutor::NativeModuleProxy : public jsi::HostObject {
public:
NativeModuleProxy(std::shared_ptr<JSINativeModules> nativeModules)
: weakNativeModules_(nativeModules) {}
Value get(Runtime& rt, const PropNameID& name) override {
if (name.utf8(rt) == "name" ) {
return jsi::String::createFromAscii(rt, "NativeModules" );
}
auto nativeModules = weakNativeModules_.lock();
if (!nativeModules) {
return nullptr;
}
return nativeModules->getModule(rt, name);
}
...
};
所以这里调用的是JSINativeModules->getModule,核心作用:
- 在m_objects缓存中查找模块,有则返回
- createModule:创建模块
- 将模块缓存到m_objects中
- 返回Value(rt, result->second)
std::optional<Object> JSINativeModules::createModule(
Runtime& rt,
const std::string& name) {
...
if (!m_genNativeModuleJS) {
m_genNativeModuleJS =
rt.global().getPropertyAsFunction(rt, "__fbGenNativeModule" );
}
auto result = m_moduleRegistry->getConfig(name);
if (!result.has_value()) {
return std::nullopt;
}
Value moduleInfo = m_genNativeModuleJS->call(
rt,
valueFromDynamic(rt, result->config),
static_cast<double>(result->index));
CHECK(!moduleInfo.isNull()) << "Module returned from genNativeModule is null" ;
CHECK(moduleInfo.isObject())
<< "Module returned from genNativeModule isn't an Object" ;
std::optional<Object> module(
moduleInfo.asObject(rt).getPropertyAsObject(rt, "module" ));
return module;
}
这里有个重要步骤
- 查找JS中的__fbGenNativeModule全局方法,其实就是genModule
- m_moduleRegistry->getConfig:获取模块
- 调用__fbGenNativeModule全局方法
- 返回module
//NativeModules.js
// export this method as a global so we can call it from native
global.__fbGenNativeModule = genModule;
生成模块
getConfig核心作用:使用一个JSON 数组描述一个NaitveModule的所有内容
std::optional<ModuleConfig> ModuleRegistry::getConfig(const std::string& name) {
// Initialize modulesByName_
if (modulesByName_.empty() && !modules_.empty()) {
moduleNames();
}
auto it = modulesByName_.find(name);
}
- moduleNames:构建一个map对象modulesByName_,key=模块名、value=模块在modules_中的索引
- modulesByName_.find返回模块索引
size_t index = it->second;
CHECK(index < modules_.size());
NativeModule* module = modules_[index].get();
// string name, object constants, array methodNames (methodId is index),
// [array promiseMethodIds], [array syncMethodIds]
folly::dynamic config = folly::dynamic::array(name);
std::vector<MethodDescriptor> methods = module->getMethods();
folly::dynamic methodNames = folly::dynamic::array;
folly::dynamic promiseMethodIds = folly::dynamic::array;
folly::dynamic syncMethodIds = folly::dynamic::array;
for (auto& descriptor : methods) {
// TODO: # 10487027 compare tags instead of doing string comparison?
methodNames.push_back(std::move(descriptor.name));
if (descriptor.type == "promise" ) {
promiseMethodIds.push_back(methodNames.size() - 1);
} else if (descriptor.type == "sync" ) {
syncMethodIds.push_back(methodNames.size() - 1);
}
}
if (!methodNames.empty()) {
config.push_back(std::move(methodNames));
if (!promiseMethodIds.empty() || !syncMethodIds.empty()) {
config.push_back(std::move(promiseMethodIds));
if (!syncMethodIds.empty()) {
config.push_back(std::move(syncMethodIds));
}
}
}
然后获取到对应的NativeModule,并创建了一个JSON 数组,结构为:
[moduleName, constants, methodNames, promiseMethodIds?, syncMethodIds?]
// [0] [1] [2] [3] [4]
- constants:调用
module->getConstants()获取导出常量(如{ "initialCount": 0 }) - methodNames:调用
module->getMethods()获取所有方法名 - promiseMethodIds:记录哪些方法返回 Promise(索引列表)
- syncMethodIds:记录哪些方法是同步的(索引列表)
这里不太好理解,我给大家举个例子就明白了,假设你有一个原生模块 MyButtonModule
@ReactModule(name = MyButtonModule.NAME)
class MyButtonModule(private val reactContext: ReactApplicationContext) :
ReactContextBaseJavaModule(reactContext) {
companion object {
const val NAME = "MyButton"
}
override fun getName(): String = NAME
// ── 常量导出 ──────────────────────────────────────
// getConfig 返回的 config[1]
override fun getConstants(): MutableMap<String, Any> {
return mutableMapOf(
"BUTTON_HEIGHT" to 44,
"BUTTON_COLOR" to "#007AFF",
)
}
// ── 异步方法(Async) ────────────────────────────────
// getConfig 返回的 config[2] 中的普通方法
@ReactMethod
fun showAlert(message: String) {
currentActivity?.runOnUiThread {
Toast.makeText(it, message, Toast.LENGTH_SHORT).show()
}
}
@ReactMethod
fun getButtonState() {
// 无返回值的异步调用,JS 侧无法获取结果
// 如果需要返回值,应使用 Promise 或 Callback
}
// ── Callback 回调 ──────────────────────────────────
// async 方法 + 最后参数为 Callback → genMethod 中走 nonPromiseMethodWrapper
// JS 侧传入的 callback 会被识别为 onSuccess / onFail
// 单个 callback
@ReactMethod
fun getButtonInfo(callback: Callback) {
val map = Arguments.createMap().apply {
putInt("height", 44)
putString("color", "#007AFF")
putBoolean("enabled", true)
}
callback.invoke(map)
}
// ── Promise 方法 ──────────────────────────────────
// getConfig 返回的 config[3] 中的索引对应的方法
@ReactMethod
fun requestPermission(promise: Promise) {
try {
// 模拟权限请求
val granted = true
if (granted) {
promise.resolve(true)
} else {
promise.reject("PERMISSION_DENIED", "User denied permission")
}
} catch (e: Exception) {
promise.reject("ERROR", e)
}
}
// ── 同步方法(Sync) ────────────────────────────────
// getConfig 返回的 config[4] 中的索引对应的方法
// 注意:同步方法不能返回 null
@ReactMethod(isBlockingSynchronousMethod = true)
fun isAvailable(): Boolean {
return true
}
}
那么 getConfig("MyButton") 返回的 config 数组是:
[
"MyButton", // [0] 模块名
{ // [1] 常量
"BUTTON_HEIGHT": 44,
"BUTTON_COLOR": "#007AFF"
},
[ // [2] 所有方法名(按声明顺序)
"showAlert",
"getButtonState",
"requestPermission",
"isAvailable"
],
[2], // [3] Promise 方法的索引 → requestPermission
[3] // [4] Sync 方法的索引 → isAvailable
]
最后返回值结构 ModuleConfig
struct ModuleConfig {
size_t index; // 模块在 modules_ 数组中的索引
folly::dynamic config; // JSON 配置数组
};
继续回到调用__fbGenNativeModule=genModule全局方法
function genModule(
config: ?ModuleConfig,
moduleID: number,
): ?{
name: string,
module?: {...},
...
} {
if (!config) {
return null;
}
//先从config中解析
const [moduleName, constants, methods, promiseMethods, syncMethods] = config;
invariant(
!moduleName.startsWith( 'RCT' ) && !moduleName.startsWith( 'RK' ),
"Module name prefixes should've been stripped by the native side " +
"but wasn't for " +
moduleName,
);
//模块中没有常量和方法
if (!constants && !methods) {
// Module contents will be filled in lazily later
return {name: moduleName};
}
const module: {[string]: mixed} = {};
methods &&
methods.forEach((methodName, methodID) => {
const isPromise =
(promiseMethods && arrayContains(promiseMethods, methodID)) || false;
const isSync =
(syncMethods && arrayContains(syncMethods, methodID)) || false;
invariant(
!isPromise || !isSync,
'Cannot have a method that is both async and a sync hook' ,
);
const methodType = isPromise ? 'promise' : isSync ? 'sync' : 'async' ;
module[methodName] = genMethod(moduleID, methodID, methodType);
});
Object.assign(module, constants);
if (module.getConstants == null) {
module.getConstants = () => constants || Object.freeze({});
} else {
console.warn(
`Unable to define method 'getConstants()' on NativeModule ' ${moduleName} ' . NativeModule ' ${moduleName} ' already has a constant or method called 'getConstants' . Please remove it.`,
);
}
if (__DEV__) {
BatchedBridge.createDebugLookup(moduleID, moduleName, methods);
}
return {name: moduleName, module};
}
- 创建module对象
- 这里遍历从config中解析的methods,获取方法类型:Promise方法、Sync方法
const module: {[string]: mixed} = {};
methods &&
methods.forEach((methodName, methodID) => {
const isPromise =
(promiseMethods && arrayContains(promiseMethods, methodID)) || false;
const isSync =
(syncMethods && arrayContains(syncMethods, methodID)) || false;
invariant(
!isPromise || !isSync,
'Cannot have a method that is both async and a sync hook' ,
);
const methodType = isPromise ? 'promise' : isSync ? 'sync' : 'async' ;
module[methodName] = genMethod(moduleID, methodID, methodType);
});
调用genMethod构造methodName对应的function,这个function在后面调用方法时会被触发
- promise方法返回promiseMethodWrapper
- 否则返回nonPromiseMethodWrapper
function genMethod(moduleID: number, methodID: number, type: MethodType) {
let fn = null;
if (type === 'promise' ) {
fn = function promiseMethodWrapper(...args: Array<mixed>) {
const enqueueingFrameError: ExtendedError = new Error();
return new Promise((resolve, reject) => {
BatchedBridge.enqueueNativeCall(
moduleID,
methodID,
args,
data => resolve(data),
errorData =>
reject(
updateErrorWithErrorData(
(errorData: $FlowFixMe),
enqueueingFrameError,
),
),
);
});
};
} else {
fn = function nonPromiseMethodWrapper(...args: Array<mixed>) {
const lastArg = args.length > 0 ? args[args.length - 1] : null;
const secondLastArg = args.length > 1 ? args[args.length - 2] : null;
const hasSuccessCallback = typeof lastArg === 'function' ;
const hasErrorCallback = typeof secondLastArg === 'function' ;
hasErrorCallback &&
invariant(
hasSuccessCallback,
'Cannot have a non-function arg after a function arg.' ,
);
// $FlowFixMe[incompatible-type]
const onSuccess: ?(mixed) => void = hasSuccessCallback ? lastArg : null;
// $FlowFixMe[incompatible-type]
const onFail: ?(mixed) => void = hasErrorCallback ? secondLastArg : null;
// $FlowFixMe[unsafe-addition]
const callbackCount = hasSuccessCallback + hasErrorCallback;
const newArgs = args.slice(0, args.length - callbackCount);
if (type === 'sync' ) {
return BatchedBridge.callNativeSyncHook(
moduleID,
methodID,
newArgs,
onFail,
onSuccess,
);
} else {
BatchedBridge.enqueueNativeCall(
moduleID,
methodID,
newArgs,
onFail,
onSuccess,
);
}
};
}
// $FlowFixMe[prop-missing]
fn.type = type;
return fn;
}
methods遍历完成后module对象内容如下
{
showAlert(msg) { /* 通过 bridge 异步调用 index=0 */ },
getButtonState() { /* 通过 bridge 异步调用 index=1 */ },
getButtonInfo() {/* 返回 bridge, 调用 index=2 */}
requestPermission() { /* 返回 Promise, 调用 index=3 */ },
isAvailable() { /* 同步调用 index=4 */ },
}
接着构建constants
Object.assign(module, constants);
if (module.getConstants == null) {
module.getConstants = () => constants || Object.freeze({});
}
constants完成后module对象内容如下
{
BUTTON_HEIGHT: 44,
BUTTON_COLOR: "#007AFF",
showAlert(msg) { /* 通过 bridge 异步调用 index=0 */ },
getButtonState() { /* 通过 bridge 异步调用 index=1 */ },
getButtonInfo() {/* 返回 bridge, 调用 index=2 */}
requestPermission() { /* 返回 Promise, 调用 index=3 */ },
isAvailable() { /* 同步调用 index=4 */ },
}
最后整个genModule返回,也就是说JS 侧收到后Native返回的模块config后,会将其转化为可调用的JS对象:
{name: moduleName, module}
// JS 侧最终效果
{
name: "MyButton",
module: {
BUTTON_HEIGHT: 44,
BUTTON_COLOR: "#007AFF",
showAlert(msg) { /* 通过 bridge 异步调用 index=0 */ },
getButtonState() { /* 通过 bridge 异步调用 index=1 */ },
getButtonInfo() {/* 返回 bridge, 调用 index=2 */}
requestPermission() { /* 返回 Promise, 调用 index=3 */ },
isAvailable() { /* 同步调用 index=4 */ },
}
};
也就是说下面这个调用流程绕了一大圈干了 2 件核心事情
- 从Native层获取module配置信息
- 在JS构建一个对象,与Native层module配置信息一一对应
//JS层构建模块对象
NativeModules.MyButton --- JS层
NativeModuleProxy.get --- C++层
m_moduleRegistry->getConfig --- C++层获取模块信息
genModule(config) --- JS层,将模块信息传入js
genMethod --- JS层,将模块信息转化为可调用的JS对象
|
返回JS对象<------|
//JS层调用模块方法(下面接着分析)
调用方法
接下来我们继续看方法调用
NativeModules.MyButton.xxx()
promise方法调用promiseMethodWrapper,它里面是调用
BatchedBridge.enqueueNativeCall
非promise方法调用nonPromiseMethodWrapper,里面分为同步和异步
//同步调用
BatchedBridge.callNativeSyncHook
//异步调用
BatchedBridge.enqueueNativeCall
异步调用
BatchedBridge是MessageQueue
enqueueNativeCall(
moduleID: number,
methodID: number,
params: mixed[],
onFail: ?(...mixed[]) => void,
onSucc: ?(...mixed[]) => void,
): void {
this.processCallbacks(moduleID, methodID, params, onFail, onSucc);
this._queue[MODULE_IDS].push(moduleID);
this._queue[METHOD_IDS].push(methodID);
this._queue[PARAMS].push(params);
const now = Date.now();
if (
global.nativeFlushQueueImmediate &&
now - this._lastFlush >= MIN_TIME_BETWEEN_FLUSHES_MS
) {
const queue = this._queue;
this._queue = [[], [], [], this._callID];
this._lastFlush = now;
global.nativeFlushQueueImmediate(queue);
}
...
}
它核心做了这几件事
- 调用processCallbacks,保存onFail和onSucc回调,key是_callID,后续返回数据时会根据_callID找到对应的onFail和onSucc回调
processCallbacks(
moduleID: number,
methodID: number,
params: mixed[],
onFail: ?(...mixed[]) => void,
onSucc: ?(...mixed[]) => void,
): void {
if (onFail || onSucc) {
onFail && params.push(this._callID << 1);
// eslint-disable-next-line no-bitwise
onSucc && params.push((this._callID << 1) | 1);
this._successCallbacks.set(this._callID, onSucc);
this._failureCallbacks.set(this._callID, onFail);
}
...
//_callID+1,下一次使用
this._callID++;
}
- 把调用信息保存到_queue数组中
// [0] [1] [2] [3]
[moduleID数组, methodID数组, params, _callID]
- 调用nativeFlushQueueImmediate,并将_queue作为参数传递过去,它调用到C++层的HostFunction
runtime_->global().setProperty(
*runtime_,
"nativeFlushQueueImmediate" ,
Function::createFromHostFunction(
*runtime_,
PropNameID::forAscii(*runtime_, "nativeFlushQueueImmediate" ),
1,
[this](
jsi::Runtime&,
const jsi::Value&,
const jsi::Value* args,
size_t count) {
if (count != 1) {
throw std::invalid_argument(
"nativeFlushQueueImmediate arg count must be 1" );
}
callNativeModules(args[0], false);
return Value::undefined();
}));
callNativeModules中调用delegate_->callNativeModules,delegate_是JsToNativeBridge
- 将calls转换为vector,每个MethodCall包含:模块、方法、参数、回调id
struct MethodCall {
int moduleId;
int methodId;
folly::dynamic arguments;
int callId;
}
- 循环遍历所有methodCalls,并调用m_registry->callNativeMethod,m_registry是ModuleRegistry
void callNativeModules(
[[maybe_unused]] JSExecutor& executor,
folly::dynamic&& calls,
bool isEndOfBatch) override {
...
std::vector<MethodCall> methodCalls = parseMethodCalls(std::move(calls));
BridgeNativeModulePerfLogger::asyncMethodCallBatchPreprocessEnd(
(int)methodCalls.size());
// An exception anywhere in here stops processing of the batch. This
// was the behavior of the Android bridge, and since exception handling
// terminates the whole bridge, there's not much point in continuing.
for (auto& call : methodCalls) {
m_registry->callNativeMethod(
call.moduleId, call.methodId, std::move(call.arguments), call.callId);
}
...
}
在ModuleRegistry.callNativeMethod中根据moduleId找到模块NativeModule,然后调用invoke方法
modules_[moduleId]->invoke(methodId, std::move(params), callId);
要知道NativeModule是什么,我们先看看ModuleRegistry是在哪里创建的
void CatalystInstanceImpl::initializeBridge(
...
moduleRegistry_ = std::make_shared<ModuleRegistry>(buildNativeModuleList(
std::weak_ptr<Instance>(instance_),
javaModules,
cxxModules,
moduleMessageQueue_));
...
}
buildNativeModuleList中有代码如下,所以:
- Java的NativeModule是JavaNativeModule(JavaModuleWrapper.cpp)
- C++的NativeModule是CxxNativeModule(CxxNativeModule.cpp)
//ModuleRegistryBuilder.cpp
std::vector<std::unique_ptr<NativeModule>> buildNativeModuleList(
std::weak_ptr<Instance> winstance,
jni::alias_ref<jni::JCollection<JavaModuleWrapper::javaobject>::javaobject>
javaModules,
jni::alias_ref<jni::JCollection<ModuleHolder::javaobject>::javaobject>
cxxModules,
std::shared_ptr<MessageQueueThread> moduleMessageQueue) {
std::vector<std::unique_ptr<NativeModule>> modules;
if (javaModules) {
for (const auto& jm : *javaModules) {
modules.emplace_back(std::make_unique<JavaNativeModule>(
winstance, jm, moduleMessageQueue));
}
}
if (cxxModules) {
for (const auto& cm : *cxxModules) {
std::string moduleName = cm->getName();
modules.emplace_back(std::make_unique<CxxNativeModule>(
winstance,
moduleName,
cm->getProvider(moduleName),
moduleMessageQueue));
}
}
return modules;
}
回到JavaNativeModule::invoke
- messageQueueThread_:NativeModules线程
- wrapper_是对Java层中module的引用
- getMethod:找到Java层中"invoke"方法
- 然后调用该module的"invoke"方法
void JavaNativeModule::invoke(
unsigned int reactMethodId,
folly::dynamic&& params,
int callId) {
messageQueueThread_->runOnQueue(
[this, reactMethodId, params = std::move(params), callId] {
static auto invokeMethod =
wrapper_->getClass()
->getMethod<void(jint, ReadableNativeArray::javaobject)>(
"invoke" );
#ifdef WITH_FBSYSTRACE
if (callId != -1) {
fbsystrace_end_async_flow(TRACE_TAG_REACT_APPS, "native" , callId);
}
#endif
invokeMethod(
wrapper_,
static_cast<jint>(reactMethodId),
ReadableNativeArray::newObjectCxxArgs(std::move(params)).get());
});
}
那么wrapper_是什么呢,我们还是要回到初始化,看看getJavaModules返回的什么
initializeBridge(
new InstanceCallback(this),
jsExecutor,
mReactQueueConfiguration.getJSQueueThread(),
mNativeModulesQueueThread,
mNativeModuleRegistry.getJavaModules(this),
mNativeModuleRegistry.getCxxModules(),
mInspectorTarget);
/* package */ Collection<JavaModuleWrapper> getJavaModules(JSInstance jsInstance) {
ArrayList<JavaModuleWrapper> javaModules = new ArrayList<>();
for (Map.Entry<String, ModuleHolder> entry : mModules.entrySet()) {
if (!entry.getValue().isCxxModule()) {
javaModules.add(new JavaModuleWrapper(jsInstance, entry.getValue()));
}
}
return javaModules;
}
很显然wrapper_就是JavaModuleWrapper的引用,我们继续看JavaModuleWrapper中的Invoke方法
@DoNotStrip
public void invoke(int methodId, ReadableNativeArray parameters) {
if (methodId >= mMethods.size()) {
return;
}
mMethods.get(methodId).invoke(mJSInstance, parameters);
}
通过方法id找到方法再进行调用,在JavaMethodWrapper.invoke中先构建参数,然后通过mMethod.invoke调用到指定的方法
//JavaMethodWrapper.java
@Override
public void invoke(JSInstance jsInstance, ReadableArray parameters) {
...
int i = 0, jsArgumentsConsumed = 0;
try {
for (; i < mArgumentExtractors.length; i++) {
mArguments[i] =
mArgumentExtractors[i].extractArgument(jsInstance, parameters, jsArgumentsConsumed);
jsArgumentsConsumed += mArgumentExtractors[i].getJSArgumentsNeeded();
}
} catch (UnexpectedNativeTypeException | NullPointerException e) {
...
}
mMethod.invoke(mModuleWrapper.getModule(), mArguments);
....
} finally {
SystraceMessage.endSection(TRACE_TAG_REACT_JAVA_BRIDGE).flush();
}
}
到此JS->JAVA调用完整分析就完成了,异步调用不会直接返回数据,下一篇我们继续分析JAVA->JS返回数据
同步调用
同步调用的流程和前面分析的异步调用大体相似,所以同步调用我就说一下主要流程就可以了
BatchedBridge.callNativeSyncHook
Value JSIExecutor::nativeCallSyncHook(const Value* args, size_t count)
delegate_->callSerializableNativeHook
m_registry->callSerializableNativeHook
modules_[moduleId]->callSerializableNativeHook
调用到JavaNativeModule::callSerializableNativeHook后又调用method->invoke
MethodCallResult JavaNativeModule::callSerializableNativeHook(
unsigned int reactMethodId,
folly::dynamic&& params) {
// TODO: evaluate whether calling through invoke is potentially faster
if (reactMethodId >= syncMethods_.size()) {
throw std::invalid_argument(folly::to<std::string>(
"methodId " ,
reactMethodId,
" out of range [0.." ,
syncMethods_.size(),
"]" ));
}
auto& method = syncMethods_[reactMethodId];
CHECK(method.has_value() && method->isSyncHook())
<< "Trying to invoke a asynchronous method as synchronous hook" ;
return method->invoke(instance_, wrapper_->getModule(), params);
}
这里的method是MethodInvoker
std::vector<std::optional<MethodInvoker>> syncMethods_;
MethodInvoker::invoke负责从 C++ 侧调用 Java 模块的方法,并将结果转回 folly::dynamic 供 JS 侧使用
这里会根据returnType类型调用不同代码片段,不同代码片段中根据参数类型调用不同方法
MethodCallResult MethodInvoker::invoke(
std::weak_ptr<Instance>& instance,
alias_ref<JBaseJavaModule::javaobject> module,
const folly::dynamic& params) {
#ifdef WITH_FBSYSTRACE
fbsystrace::FbSystraceSection s(
TRACE_TAG_REACT_CXX_BRIDGE,
isSync_ ? "callJavaSyncHook" : "callJavaModuleMethod" ,
"method" ,
traceName_);
#endif
if (params.size() != jsArgCount_) {
throw std::invalid_argument(folly::to<std::string>(
"expected " , jsArgCount_, " arguments, got " , params.size()));
}
auto env = Environment::current();
auto argCount = signature_.size() - 2;
JniLocalScope scope(env, static_cast<int>(argCount));
std::vector<jvalue> argsStorage(
argCount + 1); // ensure we have at least 1 element
jvalue* args = argsStorage.data();
std::transform(
signature_.begin() + 2,
signature_.end(),
args,
[&instance, it = params.begin(), end = params.end()](char type) mutable {
return extract(instance, type, it, end);
});
//定义代码片段
#define PRIMITIVE_CASE(METHOD) \
{ \
auto result = env->Call##METHOD##MethodA(module.get(), method_, args); \
throwPendingJniExceptionAsCppException(); \
return folly::dynamic(result); \
}
#define PRIMITIVE_CASE_CASTING(METHOD, RESULT_TYPE) \
{ \
auto result = env->Call##METHOD##MethodA(module.get(), method_, args); \
throwPendingJniExceptionAsCppException(); \
return folly::dynamic(static_cast<RESULT_TYPE>(result)); \
}
#define OBJECT_CASE(JNI_CLASS, ACTIONS) \
{ \
auto jobject = env->CallObjectMethodA(module.get(), method_, args); \
throwPendingJniExceptionAsCppException(); \
if (!jobject) { \
return folly::dynamic(nullptr); \
} \
auto result = adopt_local(static_cast<JNI_CLASS::javaobject>(jobject)); \
return folly::dynamic(result->ACTIONS()); \
}
#define OBJECT_CASE_CASTING(JNI_CLASS, ACTIONS, RESULT_TYPE) \
{ \
auto jobject = env->CallObjectMethodA(module.get(), method_, args); \
throwPendingJniExceptionAsCppException(); \
if (!jobject) { \
return folly::dynamic(nullptr); \
} \
auto result = adopt_local(static_cast<JNI_CLASS::javaobject>(jobject)); \
return folly::dynamic(static_cast<RESULT_TYPE>(result->ACTIONS())); \
}
//根据返回类型执行不同的代码片段
char returnType = signature_.at(0);
switch (returnType) {
case 'v' :
env->CallVoidMethodA(module.get(), method_, args);
throwPendingJniExceptionAsCppException();
return std::nullopt;
case 'z' :
PRIMITIVE_CASE_CASTING(Boolean, bool)
case 'Z' :
OBJECT_CASE_CASTING(JBoolean, value, bool)
case 'i' :
PRIMITIVE_CASE(Int)
case 'I' :
OBJECT_CASE(JInteger, value)
case 'd' :
PRIMITIVE_CASE(Double)
case 'D' :
OBJECT_CASE(JDouble, value)
case 'f' :
PRIMITIVE_CASE(Float)
case 'F' :
OBJECT_CASE(JFloat, value)
case 'S' :
OBJECT_CASE(JString, toStdString)
case 'M' :
OBJECT_CASE(WritableNativeMap, cthis()->consume)
case 'A' :
OBJECT_CASE(WritableNativeArray, cthis()->consume)
default:
LOG(FATAL) << "Unknown return type: " << returnType;
return std::nullopt;
}
}
最后数据通过folly::dynamic返回到JS 侧