news 2026/2/28 14:42:42

Rect Native bridging 源码分析--Array.h

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Rect Native bridging 源码分析--Array.h

代码目录:

packages/react-native/ReactCommon/react/bridging/Base.h

源代码:

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #include <jsi/jsi.h> #include <react/bridging/Convert.h> #include <cstdint> #include <memory> #include <type_traits> namespace facebook::react { class CallInvoker; template <typename T, typename = void> struct Bridging; template <> struct Bridging<void> { // Highly generic code may result in "casting" to void. static void fromJs(jsi::Runtime & /*unused*/, const jsi::Value & /*unused*/) {} }; namespace bridging { namespace detail { template <typename F> struct function_wrapper; template <typename ClassT, typename ReturnT, typename... ArgsT> struct function_wrapper<ReturnT (ClassT::*)(ArgsT...)> { using type = std::function<ReturnT(ArgsT...)>; }; template <typename ClassT, typename ReturnT, typename... ArgsT> struct function_wrapper<ReturnT (ClassT::*)(ArgsT...) const> { using type = std::function<ReturnT(ArgsT...)>; }; template <typename T, typename = void> struct bridging_wrapper { using type = remove_cvref_t<T>; }; // Convert lambda types to move-only function types since we can't specialize // Bridging templates for arbitrary lambdas. template <typename T> struct bridging_wrapper<T, std::void_t<decltype(&remove_cvref_t<T>::operator())>> : function_wrapper<decltype(&remove_cvref_t<T>::operator())> {}; } // namespace detail template <typename T> using bridging_t = typename detail::bridging_wrapper<T>::type; template <typename ReturnT, typename JSArgT> requires is_jsi_v<JSArgT> auto fromJs(jsi::Runtime &rt, JSArgT &&value, const std::shared_ptr<CallInvoker> & /*unused*/) -> decltype(static_cast<ReturnT>(std::move(convert(rt, std::forward<JSArgT>(value))))) { return static_cast<ReturnT>(std::move(convert(rt, std::forward<JSArgT>(value)))); } template <typename ReturnT, typename JSArgT> auto fromJs(jsi::Runtime &rt, JSArgT &&value, const std::shared_ptr<CallInvoker> & /*unused*/) -> decltype(Bridging<remove_cvref_t<ReturnT>>::fromJs(rt, convert(rt, std::forward<JSArgT>(value)))) { return Bridging<remove_cvref_t<ReturnT>>::fromJs(rt, convert(rt, std::forward<JSArgT>(value))); } template <typename ReturnT, typename JSArgT> auto fromJs(jsi::Runtime &rt, JSArgT &&value, const std::shared_ptr<CallInvoker> &jsInvoker) -> decltype(Bridging<remove_cvref_t<ReturnT>>::fromJs(rt, convert(rt, std::forward<JSArgT>(value)), jsInvoker)) { return Bridging<remove_cvref_t<ReturnT>>::fromJs(rt, convert(rt, std::forward<JSArgT>(value)), jsInvoker); } template <typename T> requires is_jsi_v<T> auto toJs(jsi::Runtime &rt, T &&value, const std::shared_ptr<CallInvoker> & /*unused*/ = nullptr) -> remove_cvref_t<T> { return convert(rt, std::forward<T>(value)); } template <typename T> auto toJs(jsi::Runtime &rt, T &&value, const std::shared_ptr<CallInvoker> & /*unused*/ = nullptr) -> decltype(Bridging<bridging_t<T>>::toJs(rt, std::forward<T>(value))) { return Bridging<bridging_t<T>>::toJs(rt, std::forward<T>(value)); } template <typename T> auto toJs(jsi::Runtime &rt, T &&value, const std::shared_ptr<CallInvoker> &jsInvoker) -> decltype(Bridging<bridging_t<T>>::toJs(rt, std::forward<T>(value), jsInvoker)) { return Bridging<bridging_t<T>>::toJs(rt, std::forward<T>(value), jsInvoker); } template <typename, typename = jsi::Value, typename = void> inline constexpr bool supportsFromJs = false; template <typename T, typename Arg> inline constexpr bool supportsFromJs< T, Arg, std::void_t<decltype(fromJs<T>(std::declval<jsi::Runtime &>(), std::declval<Arg>(), nullptr))>> = true; template <typename T> inline constexpr bool supportsFromJs< T, jsi::Value, std::void_t<decltype(fromJs<T>(std::declval<jsi::Runtime &>(), std::declval<jsi::Value>(), nullptr))>> = true; template <typename, typename = jsi::Value, typename = void> inline constexpr bool supportsToJs = false; template <typename JSReturnT, typename ReturnT> inline constexpr bool supportsToJs< JSReturnT, ReturnT, std::void_t<decltype(toJs(std::declval<jsi::Runtime &>(), std::declval<JSReturnT>(), nullptr))>> = std::is_convertible_v<decltype(toJs(std::declval<jsi::Runtime &>(), std::declval<JSReturnT>(), nullptr)), ReturnT>; template <typename ReturnT> inline constexpr bool supportsToJs< ReturnT, jsi::Value, std::void_t<decltype(toJs(std::declval<jsi::Runtime &>(), std::declval<ReturnT>(), nullptr))>> = std::is_convertible_v<decltype(toJs(std::declval<jsi::Runtime &>(), std::declval<ReturnT>(), nullptr)), jsi::Value>; } // namespace bridging } // namespace facebook::react

概述

该头文件隶属于facebook::react命名空间,是 React Native 跨端框架中 C++ 层与 JavaScript 层(基于 JSI,JavaScript Interface)数据交互的核心基础模块。它定义了通用的桥接接口、类型包装工具、双向转换核心方法(fromJs/toJs)以及兼容性判断常量,为上层各类数据类型(如集合、自定义对象等)的跨语言转换提供统一的底层支撑。

核心命名空间

命名空间层级说明对外可见性
facebook::react顶层命名空间,包含核心桥接结构体与对外接口公开
facebook::react::bridging核心功能命名空间,封装fromJs/toJs方法与类型工具公开
facebook::react::bridging::detail内部辅助命名空间,提供类型包装的底层实现,避免对外暴露冗余细节私有(不建议直接使用)

1. 前置声明与核心模板

1.1 类前置声明

class CallInvoker;
  • 功能:声明 JS 调用器类型,用于支撑 C++ 与 JS 之间的同步 / 异步方法调用,是桥接转换的依赖参数。
  • 说明:具体实现不在当前头文件中,仅提供前置声明以满足编译依赖。

1.2 核心桥接模板(前置声明)

template <typename T, typename = void> struct Bridging;
  • 功能:通用桥接结构体模板,是所有具体类型(如集合、基本类型)桥接实现的基模板。
  • 说明:
    1. 模板参数T为待桥接的目标类型(C++ 类型)。
    2. 第二个模板参数为占位符(SFINAE 特性支持),用于后续模板特化。
    3. 本身无默认实现,需针对具体类型进行模板特化(如之前的std::vector<T>std::array<T, N>等)。

1.3void类型桥接特化

template <> struct Bridging<void>;
  • 功能:为void类型提供专属桥接实现,适配 “无返回值 / 无数据” 的跨语言交互场景。
  • 核心方法:
    方法签名功能实现细节
    static void fromJs(jsi::Runtime & /*unused*/, const jsi::Value & /*unused*/)JS 类型 → C++void类型空实现,仅用于满足通用桥接接口规范,忽略所有输入参数

2. 内部辅助类型工具(bridging::detail

该命名空间提供类型包装与转换的底层工具,用于统一处理 lambda 表达式、普通函数等可调用对象的类型适配。

2.1function_wrapper结构体

模板定义
template <typename F> struct function_wrapper; // 普通成员函数特化 template <typename ClassT, typename ReturnT, typename... ArgsT> struct function_wrapper<ReturnT (ClassT::*)(ArgsT...)>; // const 成员函数特化 template <typename ClassT, typename ReturnT, typename... ArgsT> struct function_wrapper<ReturnT (ClassT::*)(ArgsT...) const>;
  • 功能:将类成员函数指针类型包装为std::function类型,统一可调用对象的类型接口。
  • 核心别名:using type = std::function<ReturnT(ArgsT...)>,暴露包装后的std::function类型。
  • 适用场景:处理 lambda 表达式(编译器会将非捕获 lambda 隐式转换为成员函数指针)的类型适配。

2.2bridging_wrapper结构体

模板定义
template <typename T, typename = void> struct bridging_wrapper; // lambda 类型特化 template <typename T> struct bridging_wrapper<T, std::void_t<decltype(&remove_cvref_t<T>::operator())>>;
  • 功能:
    1. 默认实现:移除类型T的 const、volatile 修饰符与引用特性,返回纯净类型(using type = remove_cvref_t<T>)。
    2. 特化实现:针对 lambda 类型,通过function_wrapper将其包装为std::function类型,解决任意 lambda 无法直接进行Bridging模板特化的问题。
  • 依赖:remove_cvref_t<T>(C++17 类型特性,移除类型的 const/volatile/ 引用修饰)。

3. 公开类型别名(bridging::bridging_t

template <typename T> using bridging_t = typename detail::bridging_wrapper<T>::type;
  • 功能:对外暴露的通用类型包装别名,简化bridging_wrapper的使用。
  • 作用:
    1. 对普通类型:返回移除 cv 修饰与引用后的纯净类型。
    2. 对 lambda 类型:返回包装后的std::function类型。
    3. 为上层Bridging模板提供统一的类型输入,减少类型适配的冗余代码。

4. 核心双向转换方法(bridging命名空间)

提供三组重载的fromJs(JS → C++)和toJs(C++ → JS)方法,通过 SFINAE 特性实现编译期自动匹配最优转换逻辑,兼顾灵活性与效率。

4.1fromJs方法:JS 类型 → C++ 类型

功能:将 JSI 类型(如jsi::Valuejsi::Array)转换为目标 C++ 类型,提供 3 种重载形式以适配不同场景。

重载形式模板约束 / 特性方法签名核心适用场景实现逻辑
重载 1要求JSArgT是 JSI 类型(is_jsi_v<JSArgT>auto fromJs(jsi::Runtime &rt, JSArgT &&value, const std::shared_ptr<CallInvoker> & /*unused*/)基础 JSI 类型直接转换为 C++ 基础类型(如jsi::Numberint/double1. 调用convert函数完成 JSI 类型内部转换2. 通过static_cast<ReturnT>转换为目标 C++ 类型3. 忽略CallInvoker参数(基础类型转换无需 JS 调用)
重载 2依赖Bridging模板的无CallInvoker版本fromJs方法auto fromJs(jsi::Runtime &rt, JSArgT &&value, const std::shared_ptr<CallInvoker> & /*unused*/)自定义类型 / 集合类型转换(无需 JS 调用器的场景)1. 先通过convert函数预处理JSArgT类型2. 调用Bridging<remove_cvref_t<ReturnT>>::fromJs完成具体转换3. 忽略CallInvoker参数
重载 3依赖Bridging模板的带CallInvoker版本fromJs方法auto fromJs(jsi::Runtime &rt, JSArgT &&value, const std::shared_ptr<CallInvoker> &jsInvoker)需异步 / 同步调用 JS 方法的复杂类型转换(如跨线程数据交互)1. 先通过convert函数预处理JSArgT类型2. 调用Bridging<remove_cvref_t<ReturnT>>::fromJs并传入jsInvoker3. 支持复杂的 JS 层交互依赖

4.2toJs方法:C++ 类型 → JS 类型

功能:将 C++ 类型转换为 JSI 类型(如jsi::Valuejsi::Array),同样提供 3 种重载形式,与fromJs对称设计。

重载形式模板约束 / 特性方法签名核心适用场景实现逻辑
重载 1要求T是 JSI 类型(is_jsi_v<T>auto toJs(jsi::Runtime &rt, T &&value, const std::shared_ptr<CallInvoker> & /*unused*/ = nullptr)基础 JSI 类型直接透传 / 转换1. 调用convert函数完成 JSI 类型内部优化2. 返回移除 cv 修饰与引用后的 JSI 类型3.CallInvoker为可选默认参数(默认nullptr
重载 2依赖Bridging模板的无CallInvoker版本toJs方法auto toJs(jsi::Runtime &rt, T &&value, const std::shared_ptr<CallInvoker> & /*unused*/ = nullptr)自定义类型 / 集合类型转换(无需 JS 调用器的场景)1. 通过bridging_t<T>包装目标 C++ 类型2. 调用Bridging<bridging_t<T>>::toJs完成具体转换3.CallInvoker为可选默认参数
重载 3依赖Bridging模板的带CallInvoker版本toJs方法auto toJs(jsi::Runtime &rt, T &&value, const std::shared_ptr<CallInvoker> &jsInvoker)需异步 / 同步调用 JS 方法的复杂类型转换1. 通过bridging_t<T>包装目标 C++ 类型2. 调用Bridging<bridging_t<T>>::toJs并传入jsInvoker3. 支持复杂的 JS 层交互依赖

关键依赖说明

  • convert函数:内部工具函数,负责 JSI 类型之间的基础转换(如jsi::Valuejsi::Array),具体实现不在当前头文件。
  • jsi::Runtime &rt:JSI 运行时环境引用,提供 JS 层执行上下文,是所有转换方法的必备参数。

5. 兼容性判断常量(bridging命名空间)

提供编译期常量supportsFromJssupportsToJs,用于判断某类型是否支持双向桥接转换,支持模板元编程场景下的条件分支选择。

5.1supportsFromJs:判断是否支持 JS → C++ 转换

定义
template <typename, typename = jsi::Value, typename = void> inline constexpr bool supportsFromJs = false; // 特化 1:针对自定义 Arg 类型 template <typename T, typename Arg> inline constexpr bool supportsFromJs<...> = true; // 特化 2:默认针对 jsi::Value 类型 template <typename T> inline constexpr bool supportsFromJs<...> = true;
  • 类型:编译期constexpr bool常量。
  • 功能:判断Arg类型(默认jsi::Value)是否能转换为T类型(C++ 类型)。
  • 判定逻辑:若fromJs<T>(rt, Arg, nullptr)表达式合法(编译通过),则值为true,否则为false

5.2supportsToJs:判断是否支持 C++ → JS 转换

定义
template <typename, typename = jsi::Value, typename = void> inline constexpr bool supportsToJs = false; // 特化 1:针对自定义 ReturnT 类型 template <typename JSReturnT, typename ReturnT> inline constexpr bool supportsToJs<...> = std::is_convertible_v<...>; // 特化 2:默认针对 jsi::Value 类型 template <typename ReturnT> inline constexpr bool supportsToJs<...> = std::is_convertible_v<...>;
  • 类型:编译期constexpr bool常量。
  • 功能:判断JSReturnT类型(C++ 类型)是否能转换为ReturnT类型(默认jsi::Value,JS 类型)。
  • 判定逻辑:
    1. 先判断toJs(rt, JSReturnT, nullptr)表达式是否合法。
    2. 再通过std::is_convertible_v判断转换结果是否能隐式转换为目标ReturnT类型。
    3. 两者均满足则值为true,否则为false

6. 核心特性总结

  1. 统一接口:通过Bridging模板、fromJs/toJs重载方法,为所有类型提供一致的桥接接口,降低上层使用成本。
  2. 编译期优化:利用 SFINAE 特性、constexpr常量,在编译期完成方法匹配与兼容性判断,无运行期额外开销。
  3. 灵活适配
    • 支持 lambda 表达式包装,适配可调用对象的桥接需求。
    • 提供 3 种重载形式,适配基础类型、复杂类型、需 JS 调用器的场景。
  4. 分层设计:通过detail命名空间隔离底层实现,对外暴露简洁的类型别名与方法,兼顾封装性与易用性。
  5. 扩展性强:仅需对新类型进行Bridging模板特化,即可接入现有桥接体系,无需修改核心逻辑。

7. 注意事项

  1. 该模块为基础底层组件,不直接提供具体类型的桥接实现(需依赖上层特化,如集合类型桥接)。
  2. CallInvoker仅为参数传递,具体功能实现需依赖外部模块。
  3. 依赖 C++17 及以上标准(使用remove_cvref_tstd::void_tconstexpr等特性)。
  4. 依赖 JSI 库(jsi::Runtimejsi::Valuejsi::Array等类型),使用时需引入对应依赖。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/26 10:39:25

让你的平板秒变电脑扩展屏:Weylus平板扩展神器使用指南

让你的平板秒变电脑扩展屏&#xff1a;Weylus平板扩展神器使用指南 【免费下载链接】Weylus Use your tablet as graphic tablet/touch screen on your computer. 项目地址: https://gitcode.com/gh_mirrors/we/Weylus 还在为电脑屏幕太小而烦恼吗&#xff1f;想用平板的…

作者头像 李华
网站建设 2026/2/28 6:25:36

OpenCV智能文档矫正:从倾斜照片到专业扫描的进阶之路

你是否曾经为了将手机拍摄的倾斜文档转化为标准扫描件而苦恼&#xff1f;当商务合同、学习笔记、身份证件等文档需要电子化存档时&#xff0c;歪斜的拍摄角度总是让后续处理变得困难重重。借助OpenCV计算机视觉库的强大功能&#xff0c;我们可以轻松实现从随意拍摄到专业扫描的…

作者头像 李华
网站建设 2026/2/23 10:15:50

Apache Pulsar测试框架终极指南:从入门到精通

Apache Pulsar测试框架终极指南&#xff1a;从入门到精通 【免费下载链接】pulsar Apache Pulsar - distributed pub-sub messaging system 项目地址: https://gitcode.com/gh_mirrors/pulsar28/pulsar Apache Pulsar作为新一代分布式消息系统&#xff0c;其完善的测试框…

作者头像 李华
网站建设 2026/2/27 1:19:09

RuoYi-Vue3企业级管理系统:5分钟快速构建权限管理后台

RuoYi-Vue3企业级管理系统&#xff1a;5分钟快速构建权限管理后台 【免费下载链接】RuoYi-Vue3 &#x1f389; (RuoYi)官方仓库 基于SpringBoot&#xff0c;Spring Security&#xff0c;JWT&#xff0c;Vue3 & Vite、Element Plus 的前后端分离权限管理系统 项目地址: ht…

作者头像 李华
网站建设 2026/2/25 4:48:19

揭秘Python 3.13兼容性问题:如何快速定位并修复旧代码中的致命错误

第一章&#xff1a;Python 3.13兼容性问题概述Python 3.13作为最新发布的主版本&#xff0c;引入了多项底层优化和语法改进&#xff0c;同时也带来了一些破坏性变更&#xff0c;影响现有项目的平滑升级。开发者在迁移过程中需特别关注标准库调整、C API变动以及第三方依赖的适配…

作者头像 李华
网站建设 2026/2/20 6:13:31

FastAPI响应格式深度定制全攻略(99%开发者忽略的关键细节)

第一章&#xff1a;FastAPI响应格式定制的核心概念在构建现代Web API时&#xff0c;响应格式的灵活性与一致性至关重要。FastAPI通过Pydantic模型和内置的响应处理机制&#xff0c;为开发者提供了强大的响应定制能力。其核心在于利用类型提示与自动序列化机制&#xff0c;将Pyt…

作者头像 李华