Platform Adapter & Inversion of Control
Relevant source files
The following files were used as context for generating this wiki page:
The Platform Adapter is a core architectural component that implements Inversion of Control (IoC) within the RunAnywhere SDK ecosystem. It allows the cross-platform C++ core (runanywhere-commons) to access host-specific services—such as file I/O, secure storage, logging, and networking—without directly depending on platform-specific APIs.
Each platform SDK (Swift, Kotlin, React Native, etc.) populates a flat C struct of function pointers, known as rac_platform_adapter_t, and passes it to the core during initialization. This mechanism ensures the core remains portable while delegating I/O and hardware-bound operations to the optimized implementations provided by the host environment.
Sources: AGENTS.md:126-130, core/README.md:104-106, core/AGENTS.md:125-127
Architecture and Design
The architecture relies on a "Push" model where the host environment pushes its capabilities into the core library. The rac_platform_adapter_t struct defines the contract between the portable core and the platform-specific wrappers.
The diagram shows the Inversion of Control flow where the Host SDK provides implementations that the C++ Core consumes through an abstract interface.
Sources: core/README.md:25-50, AGENTS.md:126-130
Initialization Phases
The SDK follows a two-phase initialization pattern across all platforms:
- Phase 1 (Synchronous): The host loads native libraries (e.g.,
librunanywhere_jni.so), registers the platform adapter, and configures basic services like logging and telemetry. - Phase 2 (Asynchronous): The core performs high-level tasks like authentication, device registration, and fetching model assignments.
Sources: bindings/kotlin/AGENTS.md:85-95, AGENTS.md:131-133, bindings/react-native/AGENTS.md:151-160
The Platform Adapter Interface
The rac_platform_adapter_t struct is defined in rac_platform_adapter.h. It categorizes platform services into mandatory and optional slots.
Mandatory and Optional Slots
The core validates the adapter during rac_init(). If mandatory slots are missing, initialization fails with RAC_ERROR_ADAPTER_NOT_SET.
| Category | Functions | Purpose |
|---|---|---|
| Mandatory | file_exists, file_read, file_write, file_delete | Basic file system operations for model management and state. |
| Mandatory | secure_set, secure_get, secure_delete | Access to secure hardware (Keychain, Android Keystore, DPAPI). |
| Mandatory | log, now_ms | System logging and high-resolution timing. |
| Optional | get_memory_info | Provides hardware telemetry (falls back to defaults if NULL). |
| Optional | http_download, http_cancel | Direct file downloads via host networking stack. |
| Optional | file_list_directory, is_non_empty_directory | Directory traversal for model discovery. |
Sources: core/include/rac/core/rac_platform_adapter.h:17-80, core/AGENTS.md:131-138
Secure Storage Implementation
Each platform implements the secure_* functions using their respective secure enclaves:
- iOS/macOS: Uses the Keychain.
- Android: Uses the Android Keystore via
SecureStorageManager.kt. - Windows: Uses DPAPI.
- React Native: Delegated to the native iOS/Android implementation via JSI.
Sources: AGENTS.md:104-106, bindings/react-native/AGENTS.md:118-121
HTTP Transport Inversion
While the Platform Adapter handles basic I/O, networking uses a specific vtable pattern defined by rac_http_transport_ops_t. This prevents the core from needing a heavy dependency like libcurl on mobile platforms.
The sequence diagram illustrates how a model download is initiated by the core but executed by the host's networking stack.
Sources: bindings/kotlin/AGENTS.md:106-110, bindings/react-native/AGENTS.md:129-132, AGENTS.md:143-145
Platform-Specific Networking
- Apple Platforms: Uses
URLSessionHttpTransport. - Android: Uses
OkHttpTransport.ktregistered into the C++ vtable via JNI. - Web: Uses
emscripten_fetch. - Desktop: Uses
libcurlviarac_desktop_http_transport_register()whenRAC_DESKTOP_ADAPTERis enabled.
Sources: AGENTS.md:143-145, core/AGENTS.md:209-211, bindings/kotlin/AGENTS.md:106-107
Architecture Invariants
- ABI Stability: The adapter struct includes an
abi_versionandstruct_size. The core rejects mismatches withRAC_ERROR_ABI_VERSION_MISMATCH. - No Direct I/O: C++ code must never call platform I/O APIs (like
fopenorstd::cout) directly. It must always route through the adapter. - Thread Safety: The host-provided logging implementation must be thread-safe as it is called from multiple background inference threads.
- Memory Ownership: For functions like
file_read, the core typically manages the buffer, while the adapter performs the copy.
Sources: core/AGENTS.md:129-130, core/include/rac/core/rac_platform_adapter.h:12-15, core/AGENTS.md:132-133
Summary
The Platform Adapter and Inversion of Control pattern allow the RunAnywhere SDK to achieve broad platform support while maintaining a single, high-performance C++ core. By delegating OS-level responsibilities to the host SDKs, the core avoids platform-specific bloat and ensures that operations like secure storage and networking benefit from native optimizations and security features.
Sources: core/README.md:104-106, AGENTS.md:95-97