Native C/C++ Library Bindings for Mobile Apps
C and C++ libraries are standard where performance is critical: video processing (FFmpeg, x264), cryptography (OpenSSL, libsodium), computer vision (OpenCV), audio (Opus, WebRTC), physics engines (Bullet, Box2D). Mobile platforms provide direct native code access—question is how to write proper bindings.
Android: JNI and Android NDK
Android calls native code via JNI (Java Native Interface). Binding is C/C++ function layer with names like Java_com_example_MyClass_nativeMethod that Dalvik/ART automatically links with Java/Kotlin methods marked external.
// Kotlin
class ImageProcessor {
external fun processFrame(pixels: ByteArray, width: Int, height: Int): ByteArray
companion object {
init { System.loadLibrary("imageprocessor") }
}
}
// C++
extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_example_ImageProcessor_processFrame(
JNIEnv* env, jobject thiz,
jbyteArray pixels, jint width, jint height) {
auto* input = env->GetByteArrayElements(pixels, nullptr);
// call OpenCV or custom logic
env->ReleaseByteArrayElements(pixels, input, JNI_ABORT);
// ...
}
Critical: memory management at JNI boundary. GetByteArrayElements with flag 0 copies array (safe, slow). GetByteArrayElements with JNI_ABORT doesn't copy changes back. For performant image processing use GetDirectBufferAddress with ByteBuffer.allocateDirect()—shared memory, no copy.
CMakeLists.txt via Android NDK: specify target_link_libraries for pre-compiled .a or .so libraries. For OpenCV: find_package(OpenCV REQUIRED) if building from source, or manual link libopencv_core.a + libopencv_imgproc.a via add_library(opencv STATIC IMPORTED). Binary size matters: OpenCV static linking adds 8–15 MB per ABI. Use abiFilters "arm64-v8a", "x86_64"—remove unnecessary ABI.
Exception handling in JNI. C++ exceptions don't pass through JNI automatically. Wrap in try/catch on C++ side, throw Java exception via env->ThrowNew(env->FindClass("java/lang/RuntimeException"), message).
iOS: Objective-C Bridging and Swift/C++ Interop
iOS C code connects directly—Swift and Objective-C share same runtime with C. For C++ need Objective-C++ (.mm files).
// ImageProcessorBridge.mm—Objective-C++ wrapper
#include "opencv2/opencv.hpp"
#import "ImageProcessorBridge.h"
@implementation ImageProcessorBridge
- (NSData *)processFrame:(NSData *)pixelData width:(int)w height:(int)h {
cv::Mat mat(h, w, CV_8UC4, (void*)pixelData.bytes);
// process
NSData *result = ...;
return result;
}
@end
Swift calls Objective-C via bridging header (-Bridging-Header.h). Can't call C++ directly from Swift until Swift 5.9 with experimental Swift/C++ Interop—allows importing C++ types directly via import CxxModule. In production with Xcode 15, this is working for simple C++ API without templates and virtual inheritance.
XCFramework with native library. For pre-compiled C++ library—build .xcframework with lipo create for Device (arm64) and Simulator (arm64 + x86_64). Apple Silicon Simulator needs arm64, Intel Mac needs x86_64; fat binary via lipo combines both.
OpenCV on iOS. Official opencv2.framework (or xcframework) connects via CocoaPods (pod 'OpenCV') or manually. Size: ~160 MB debug, bitcode linker selects only needed modules. For App Store important to strip in Release build.
Case study. Real-time video stream processing from camera (filters, face detection): iOS—AVFoundation gives CMSampleBuffer → convert to cv::Mat via CVPixelBufferGetBaseAddress → OpenCV filter → display via MTLTexture (Metal). Android—Camera2 API → ImageReader with YUV_420_888 → convert via libyuv to RGBA → OpenCV → SurfaceView. Bindings in Objective-C++ (iOS) and JNI (Android). Performance: 1920×1080 frame processing—8–12 ms iPhone 13, 15–22 ms mid-range Android.
Build and Integration
CMake—cross-platform build system for both Android NDK and iOS (via iOS CMake toolchain). Single CMakeLists.txt for native logic, different toolchain files.
For complex C++ libraries with autoconf/Makefile—run configure && make via NDK or iOS cross-compilation toolchain. More labor-intensive but standard for OpenSSL, libsodium, FFmpeg.
Timeline
| Binding Type | Estimated Timeline |
|---|---|
| Simple C library (crypto, compression) | 2–4 weeks |
| C++ library with non-trivial API (OpenCV, FFmpeg) | 4–8 weeks |
| Full UI pipeline integration | 2–4 months |
Pricing determined individually—depends on target library API complexity and documentation availability.







