Saltar al contenido principal
Versión: 0.78
Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

Módulos Nativos Multiplataforma (C++)

Escribir un módulo en C++ es la mejor forma de compartir código independiente de la plataforma entre Android e iOS. Con módulos en C++ puro, puedes escribir tu lógica una sola vez y reutilizarla inmediatamente en todas las plataformas, sin necesidad de escribir código específico para cada sistema.

En esta guía, veremos cómo crear un Turbo Native Module en C++ puro:

  1. Crear las especificaciones (specs) de JS

  2. Configurar Codegen para generar la estructura

  3. Implementar la lógica nativa

  4. Registrar el módulo en las aplicaciones de Android e iOS

  5. Probar tus cambios en JS

El resto de esta guía asume que has creado tu aplicación ejecutando el comando:

shell
npx @react-native-community/cli@latest init SampleApp --version 0.78

1. Crear las especificaciones (specs) de JS

Los Turbo Native Modules en C++ puro son un tipo de Turbo Native Modules. Necesitan un archivo de especificaciones (también llamado archivo spec) para que Codegen pueda generar el código base. Este archivo de especificaciones también es lo que usamos para acceder al Turbo Native Module desde JS.

Los archivos spec deben escribirse en un dialecto de JS con tipado. React Native actualmente admite Flow o TypeScript.

  1. Dentro de la carpeta raíz de tu aplicación, crea una nueva carpeta llamada specs.

  2. Crea un nuevo archivo llamado NativeSampleModule.ts con el siguiente código:

advertencia

Todos los archivos spec de los Turbo Native Modules deben tener el prefijo Native, de lo contrario Codegen los ignorará.

specs/NativeSampleModule.ts
import {TurboModule, TurboModuleRegistry} from 'react-native';

export interface Spec extends TurboModule {
readonly reverseString: (input: string) => string;
}

export default TurboModuleRegistry.getEnforcing<Spec>(
'NativeSampleModule',
);

2. Configurar Codegen

El siguiente paso es configurar Codegen en tu package.json. Actualiza el archivo para incluir:

package.json
     "start": "react-native start",
"test": "jest"
},
"codegenConfig": {
"name": "AppSpecs",
"type": "modules",
"jsSrcsDir": "specs",
"android": {
"javaPackageName": "com.sampleapp.specs"
}
},
"dependencies": {

Esta configuración indica a Codegen que busque archivos spec en la carpeta specs. También le indica que genere código solo para modules y que asigne el espacio de nombres AppSpecs al código generado.

3. Escribir el código nativo

Escribir un Turbo Native Module en C++ te permite compartir código entre Android e iOS. Por lo tanto, escribiremos el código una sola vez y veremos qué cambios debemos aplicar en las plataformas para que el código en C++ pueda ser utilizado.

  1. Crea una carpeta llamada shared al mismo nivel que las carpetas android e ios.

  2. Dentro de la carpeta shared, crea un nuevo archivo llamado NativeSampleModule.h.

    shared/NativeSampleModule.h
    #pragma once

    #include <AppSpecsJSI.h>

    #include <memory>
    #include <string>

    namespace facebook::react {

    class NativeSampleModule : public NativeSampleModuleCxxSpec<NativeSampleModule> {
    public:
    NativeSampleModule(std::shared_ptr<CallInvoker> jsInvoker);

    std::string reverseString(jsi::Runtime& rt, std::string input);
    };

    } // namespace facebook::react

  3. Dentro de la carpeta shared, crea un nuevo archivo llamado NativeSampleModule.cpp.

    shared/NativeSampleModule.cpp
    #include "NativeSampleModule.h"

    namespace facebook::react {

    NativeSampleModule::NativeSampleModule(std::shared_ptr<CallInvoker> jsInvoker)
    : NativeSampleModuleCxxSpec(std::move(jsInvoker)) {}

    std::string NativeSampleModule::reverseString(jsi::Runtime& rt, std::string input) {
    return std::string(input.rbegin(), input.rend());
    }

    } // namespace facebook::react

Analicemos los dos archivos que creamos:

  • El archivo NativeSampleModule.h es el archivo de cabecera para un TurboModule en C++ puro. Las sentencias include aseguran que incluyamos las especificaciones que generará Codegen y que contienen la interfaz y la clase base que necesitamos implementar.

  • El módulo reside en el espacio de nombres facebook::react para acceder a todos los tipos definidos allí.

  • La clase NativeSampleModule es el módulo Turbo Native real y extiende la clase NativeSampleModuleCxxSpec, que contiene código auxiliar y repetitivo para que esta clase funcione como un módulo Turbo Native.

  • Finalmente, tenemos el constructor que acepta un puntero al CallInvoker para comunicarse con JS si es necesario, y el prototipo de función que debemos implementar.

El archivo NativeSampleModule.cpp contiene la implementación real de nuestro módulo Turbo Native, implementando el constructor y el método declarado en las especificaciones.

4. Registrar el módulo en la plataforma

Los siguientes pasos nos permitirán registrar el módulo en la plataforma. Este paso expone el código nativo a JS para que la aplicación React Native pueda finalmente llamar a los métodos nativos desde la capa JS.

Esta es la única vez que tendremos que escribir código específico para cada plataforma.

Android

Para asegurar que la aplicación Android pueda compilar correctamente el módulo Turbo Native en C++, necesitamos:

  1. Crear un CMakeLists.txt para acceder a nuestro código C++.

  2. Modificar build.gradle para apuntar al nuevo archivo CMakeLists.txt.

  3. Crear un archivo OnLoad.cpp en nuestra aplicación Android para registrar el nuevo módulo Turbo Native.

1. Crear el archivo CMakeLists.txt

Android usa CMake para compilar. CMake necesita acceder a los archivos que definimos en nuestra carpeta shared para poder compilarlos.

  1. Crea una nueva carpeta SampleApp/android/app/src/main/jni. La carpeta jni es donde reside el lado C++ de Android.

  2. Crea un archivo CMakeLists.txt y añade este contenido:

CMakeLists.txt
cmake_minimum_required(VERSION 3.13)

# Define the library name here.
project(appmodules)

# This file includes all the necessary to let you build your React Native application
include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake)

# Define where the additional source code lives. We need to crawl back the jni, main, src, app, android folders
target_sources(${CMAKE_PROJECT_NAME} PRIVATE ../../../../../shared/NativeSampleModule.cpp)

# Define where CMake can find the additional header files. We need to crawl back the jni, main, src, app, android folders
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ../../../../../shared)

El archivo CMake realiza lo siguiente:

  • Define la biblioteca appmodules, donde se incluirá todo el código C++ de la aplicación.

  • Carga el archivo CMake base de React Native.

  • Añade el código fuente C++ del módulo que necesitamos compilar con las directivas target_sources. Por defecto React Native ya incluye fuentes predeterminadas en la biblioteca appmodules, aquí añadimos las personalizadas. Puedes ver que debemos retroceder desde la carpeta jni hasta la carpeta shared donde reside nuestro módulo Turbo en C++.

  • Especifica dónde CMake puede encontrar los archivos de cabecera del módulo. También en este caso necesitamos retroceder desde la carpeta jni.

2. Modificar build.gradle para incluir el código C++ personalizado

Gradle es la herramienta que orquesta la compilación en Android. Debemos indicarle dónde encontrar los archivos CMake para compilar el módulo Turbo Native.

  1. Abre el archivo SampleApp/android/app/build.gradle.

  2. Agrega el siguiente bloque en el archivo Gradle, dentro del bloque android existente:

android/app/build.gradle
    buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}

+ externalNativeBuild {
+ cmake {
+ path "src/main/jni/CMakeLists.txt"
+ }
+ }
}

Este bloque indica al archivo Gradle dónde buscar el archivo CMake. La ruta es relativa a la carpeta donde reside build.gradle, por lo que necesitamos añadir la ruta al archivo CMakeLists.txt en la carpeta jni.

3. Registrar el nuevo módulo Turbo Native

El paso final es registrar el nuevo módulo Turbo Native en C++ en el runtime, para que cuando JS solicite el módulo, la aplicación sepa dónde encontrarlo y pueda devolverlo.

  1. Desde la carpeta SampleApp/android/app/src/main/jni, ejecuta el siguiente comando:
shell
curl -O https://raw.githubusercontent.com/facebook/react-native/v0.78.0/packages/react-native/ReactAndroid/cmake-utils/default-app-setup/OnLoad.cpp
  1. Luego, modifica este archivo de la siguiente manera:
android/app/src/main/jni/OnLoad.cpp
#include <DefaultComponentsRegistry.h>
#include <DefaultTurboModuleManagerDelegate.h>
#include <autolinking.h>
#include <fbjni/fbjni.h>
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <rncore.h>

+ // Include the NativeSampleModule header
+ #include <NativeSampleModule.h>

//...

std::shared_ptr<TurboModule> cxxModuleProvider(
const std::string& name,
const std::shared_ptr<CallInvoker>& jsInvoker) {
// Here you can provide your CXX Turbo Modules coming from
// either your application or from external libraries. The approach to follow
// is similar to the following (for a module called `NativeCxxModuleExample`):
//
// if (name == NativeCxxModuleExample::kModuleName) {
// return std::make_shared<NativeCxxModuleExample>(jsInvoker);
// }

+ // This code registers the module so that when the JS side asks for it, the app can return it
+ if (name == NativeSampleModule::kModuleName) {
+ return std::make_shared<NativeSampleModule>(jsInvoker);
+ }

// And we fallback to the CXX module providers autolinked
return autolinking_cxxModuleProvider(name, jsInvoker);
}

// leave the rest of the file

Estos pasos descargan el archivo original OnLoad.cpp de React Native, lo que nos permite sobrescribirlo de forma segura para cargar el módulo Turbo Nativo de C++ en la aplicación.

Una vez descargado el archivo, podemos modificarlo:

  • Incluyendo el archivo de cabecera que apunta a nuestro módulo

  • Registrando el módulo Turbo Nativo para que la aplicación pueda devolverlo cuando JS lo solicite.

Ahora puedes ejecutar yarn android desde la raíz del proyecto para ver tu aplicación compilándose correctamente.

iOS

Para garantizar que la aplicación iOS pueda compilar efectivamente el módulo Turbo Nativo de C++, necesitamos:

  1. Instalar los pods y ejecutar Codegen.

  2. Agregar la carpeta shared a nuestro proyecto de iOS.

  3. Registrar el módulo Turbo Nativo de C++ en la aplicación.

1. Instalar Pods y ejecutar Codegen

El primer paso que debemos ejecutar son los pasos habituales que realizamos cada vez que preparamos nuestra aplicación iOS. CocoaPods es la herramienta que usamos para configurar e instalar las dependencias de React Native y, como parte del proceso, también ejecutará Codegen por nosotros.

bash
cd ios
bundle install
bundle exec pod install

2. Agregar la carpeta shared al proyecto iOS

Este paso agrega la carpeta shared al proyecto para hacerla visible en Xcode.

  1. Abre el espacio de trabajo de Xcode generado por CocoaPods.
bash
cd ios
open SampleApp.xcworkspace
  1. Haz clic en el proyecto SampleApp a la izquierda y selecciona Add files to "Sample App"....

Agregar archivos a Sample App...

  1. Selecciona la carpeta shared y haz clic en Add.

Agregar archivos a Sample App...

Si hiciste todo correctamente, tu proyecto a la izquierda debería verse así:

Proyecto de Xcode

3. Registrar el módulo Turbo Nativo de C++ en tu aplicación

advertencia

Si tu aplicación tiene módulos locales escritos en C++, no podrás usar el AppDelegate en Swift que incluimos en React Native 0.77.

Si tu aplicación entra en esta categoría, omite la migración del AppDelegate a Swift y sigue usando Objective-C++ para el AppDelegate de tu aplicación.

El núcleo de React Native se desarrolla principalmente en C++ para fomentar el uso compartido de código entre iOS, Android y otras plataformas. La interoperabilidad entre Swift y C++ aún no es madura ni estable. Estamos investigando formas de resolver este problema y permitirte migrar a Swift también.

Con este último paso, indicaremos a la aplicación iOS dónde buscar para encontrar el Turbo Native Module en C++ puro.

En Xcode, abre el archivo AppDelegate.mm y modifícalo de la siguiente manera:

SampleApp/AppDelegate.mm
#import <React/RCTBundleURLProvider.h>
+ #import <RCTAppDelegate+Protected.h>
+ #import "NativeSampleModule.h"

// ...
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

+- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
+ jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
+{
+ if (name == "NativeSampleModule") {
+ return std::make_shared<facebook::react::NativeSampleModule>(jsInvoker);
+ }
+
+ return [super getTurboModule:name jsInvoker:jsInvoker];
+}

@end

Estos cambios realizan varias acciones:

  1. Importar el encabezado RCTAppDelegate+Protected para que el AppDelegate vea que está conforme al protocolo RCTTurboModuleManagerDelegate.

  2. Importar la interfaz del Turbo Native Module en C++ puro NativeSampleModule.h

  3. Sobrescribir el método getTurboModule para módulos en C++ de modo que, cuando el lado JS solicite un módulo llamado NativeSampleModule, la aplicación sepa qué módulo debe devolver.

Si ahora compilas tu aplicación desde Xcode, deberías poder completar la compilación exitosamente.

5. Pruebas de tu código

Es momento de acceder a nuestro Módulo Nativo Turbo C++ desde JS. Para hacerlo, debemos modificar el archivo App.tsx para importar el Módulo Nativo Turbo y llamarlo en nuestro código.

  1. Abre el archivo App.tsx.

  2. Reemplaza el contenido de la plantilla con el siguiente código:

App.tsx
import React from 'react';
import {
Button,
SafeAreaView,
StyleSheet,
Text,
TextInput,
View,
} from 'react-native';
import SampleTurboModule from './specs/NativeSampleModule';

function App(): React.JSX.Element {
const [value, setValue] = React.useState('');
const [reversedValue, setReversedValue] = React.useState('');

const onPress = () => {
const revString = SampleTurboModule.reverseString(value);
setReversedValue(revString);
};

return (
<SafeAreaView style={styles.container}>
<View>
<Text style={styles.title}>
Welcome to C++ Turbo Native Module Example
</Text>
<Text>Write down here the text you want to reverse</Text>
<TextInput
style={styles.textInput}
placeholder="Write your text here"
onChangeText={setValue}
value={value}
/>
<Button title="Reverse" onPress={onPress} />
<Text>Reversed text: {reversedValue}</Text>
</View>
</SafeAreaView>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
title: {
fontSize: 18,
marginBottom: 20,
},
textInput: {
borderColor: 'black',
borderWidth: 1,
borderRadius: 5,
padding: 10,
marginTop: 10,
},
});

export default App;

Las líneas interesantes en esta aplicación son:

  • import SampleTurboModule from './specs/NativeSampleModule';: esta línea importa el Módulo Nativo Turbo en la aplicación,

  • const revString = SampleTurboModule.reverseString(value); en la devolución de llamada onPress: así es como puedes usar el Módulo Nativo Turbo en tu aplicación.

advertencia

Para simplificar este ejemplo y mantenerlo breve, importamos directamente el archivo de especificaciones en nuestra aplicación. La mejor práctica en este caso es crear un archivo separado que encapsule las especificaciones y usar ese archivo en tu aplicación. Esto te permite preparar los datos de entrada para las especificaciones y tener más control sobre ellas en JS.

¡Felicidades, has creado tu primer Módulo Nativo Turbo en C++!

Android
iOS
Android Video
iOS video