skip to content

In React Native, what is a pure C++ Turbo Module, and when would a library choose it over separate Kotlin and Objective-C implementations?

level: middleimportance: nice to knowfreq 20%

answer

  1. one implementation, both platforms
  2. Codegen emits a CxxSpec base class
  3. Android: CMake plus a module provider
  4. iOS: an RCTModuleProvider class
  5. no platform SDKs from plain C++

basics

~20 s

A pure C++ Turbo Module implements a typed spec once in C++ and runs on both Android and iOS. Choose it for platform-independent logic or an existing C++ library; use Kotlin and Objective-C when the work needs platform SDKs.

solid answer

~50 s

A pure C++ Turbo Module still starts from a `Native...` TypeScript spec, but Codegen generates a C++ base class (for a spec named `NativeSampleModule`, `NativeSampleModuleCxxSpec<T>`) and you write one C++ class for both platforms. Registration is per platform: on Android the code is built with CMake and a C++ module provider returns the module for its name, which autolinking can generate for a library; on iOS an Objective-C++ class conforming to `RCTModuleProvider` returns it, mapped through `ios.modulesProvider` in `codegenConfig`. It fits logic with no platform dependency, such as parsing, search or maths, or wrapping an existing C++ library, because you write and test it once. It fits badly when the work needs platform SDKs such as views, permissions or system services, which are Kotlin and Swift or Objective-C territory. `create-react-native-library` offers both variants when you scaffold.

code

objective-cpp · 14 lines
objective-cpp
#import "PdfSearchModuleProvider.h"
#import <ReactCommon/CallInvoker.h>
#import <ReactCommon/TurboModule.h>
#import "NativePdfSearch.h"

@implementation PdfSearchModuleProvider

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
    (const facebook::react::ObjCTurboModule::InitParams &)params
{
  return std::make_shared<facebook::react::NativePdfSearch>(params.jsInvoker);
}

@end

go deeper

for a junior

Recall that a pure C++ Turbo Module is written once in C++ and used from JavaScript on both Android and iOS.

for a middle

Explain the spec, the generated CxxSpec base class, and how Android and iOS each register the C++ module so JavaScript can find it.

for a senior

Judge which parts of a library belong in shared C++ and which need platform code, and set up autolinking keys so apps do not hand-edit OnLoad.cpp.

for a principal

Weigh a shared C++ core against two native implementations: team skills, debugging cost, code reuse across apps and the long-term maintenance burden.

## What makes a module "pure C++" A **Turbo Module** is a native module that JavaScript calls through a typed spec. Usually it has two implementations: Kotlin or Java for Android and Objective-C++ or Swift for iOS. A **pure C++ Turbo Module** has one implementation, written in C++, compiled into both apps. The spec is unchanged: ```typescript import type {TurboModule} from 'react-native'; import {TurboModuleRegistry} from 'react-native'; export interface Spec extends TurboModule { readonly searchText: (pdfText: string, query: string) => Array<number>; } export default TurboModuleRegistry.getEnforcing<Spec>('NativePdfSearch'); ``` Codegen turns it into a C++ header (`<codegenConfig.name>JSI.h`) containing a base class, `NativePdfSearchCxxSpec<T>`. Your class derives from it, takes the JS call invoker in its constructor, and implements each method with C++ types. ```cpp namespace facebook::react { class NativePdfSearch : public NativePdfSearchCxxSpec<NativePdfSearch> { public: NativePdfSearch(std::shared_ptr<CallInvoker> jsInvoker); std::vector<double> searchText(jsi::Runtime& rt, std::string pdfText, std::string query); }; } // namespace facebook::react ``` ## Registering it on each platform | Platform | In an app | In a published library | |---|---|---| | Android | a `CMakeLists.txt`, a `build.gradle` pointer to it, and an `OnLoad.cpp` whose `cxxModuleProvider` returns the module when the name matches | the library's autolinking config declares its CMake file and module header, and React Native generates the provider | | iOS | an Objective-C++ class conforming to `RCTModuleProvider` whose `getTurboModule:` returns the C++ module, mapped in `codegenConfig.ios.modulesProvider` | the same provider class and mapping, shipped with the library's podspec | On Android the app's `OnLoad.cpp` falls back to `autolinking_cxxModuleProvider`, the generated function that constructs any autolinked C++ modules. For a library, the Android autolinking entry carries `cxxModuleCMakeListsPath`, `cxxModuleCMakeListsModuleName` and `cxxModuleHeaderName`, and the generated code creates the class named by the header whenever JavaScript asks for its `kModuleName`. ## When C++ is the right choice - **Platform-independent logic.** Parsing, text search, compression, maths, a rules engine. In a PDF-viewer library shared by three apps, a search index over extracted text is a good candidate; the page rendering view is not. - **An existing C++ codebase.** Wrapping a proven C++ library avoids porting it twice. - **One source of truth.** A bug fixed once is fixed on both platforms, and one test suite covers both. ## When it is the wrong choice - **The work needs platform SDKs**: views, permissions, notifications, file pickers, Bluetooth. Plain C++ cannot call Android or iOS framework APIs without extra glue, which erases the benefit. - **The team has no C++ and CMake experience.** Build errors, ABI and toolchain issues, and native crashes are harder to debug than Kotlin or Swift ones. - **A UI component.** Views are Fabric components, which have their own spec and platform view classes. ## Comparing the two approaches | | Kotlin plus Objective-C or Swift | Pure C++ | |---|---|---| | Implementations to write | two | one | | Access to platform SDKs | direct | only through extra per-platform glue | | Build tooling | Gradle and CocoaPods defaults | adds your own CMake configuration on Android | | Registration | generated spec classes and packages | a C++ provider on Android, an `RCTModuleProvider` class on iOS | | Best for | device features, system services | shared algorithms, existing C++ code | Many libraries mix the two: a shared C++ core for logic, thin Kotlin and Objective-C modules or Fabric components for anything that touches the platform. ## Legacy names you may meet Older code used `CxxModule`, `TurboCxxModule` and `RCTCxxModule`. Those legacy C++ module APIs were removed in React Native 0.84; pure C++ Turbo Modules generated from a spec are the current way to share C++. ## Scaffolding `npx create-react-native-library@latest` asks what kind of library you want. Choosing a Turbo module then lets you pick platform code (Kotlin and Objective-C) or a shared C++ implementation, and the scaffold comes with `codegenConfig` set and an example app to build both platforms against.

  • How does an app load a C++ module that it did not autolink?
    On Android, the app's `OnLoad.cpp` defines `cxxModuleProvider`, which checks the requested name against the module's `kModuleName` and returns a new instance, falling back to `autolinking_cxxModuleProvider` for everything else. On iOS, an Objective-C++ class conforming to `RCTModuleProvider` returns the module from `getTurboModule:`, and `codegenConfig.ios.modulesProvider` maps the module name to that class.
  • Why not render the PDF pages from the C++ module too?
    Rendering is a view, and views in React Native are Fabric components with their own spec and platform view classes. A Turbo Module has no view to draw into, and plain C++ cannot use the platforms' drawing frameworks without per-platform glue, so the rendering stays in the view layer.

saying these in an interview costs you the question

  • A pure C++ module needs no TypeScript spec because C++ is already typed
  • C++ modules are the recommended home for camera or permissions code
  • RCTCxxModule is the current way to share C++ between platforms
  • A pure C++ module registers itself on iOS without any provider class
  • Pure C++ modules can only be used inside apps, never published libraries