Написання біндингів до нативних C/C++ бібліотек для мобільного додатку
C та C++ бібліотеки — стандарт у областях, де продуктивність критична: обробка відео (FFmpeg, x264), криптографія (OpenSSL, libsodium), комп'ютерний зір (OpenCV), аудіо (Opus, WebRTC), фізичні движки (Bullet, Box2D). Мобільні платформи дають прямий доступ до нативного коду — питання у тому, як правильно написати біндинг.
Android: JNI та Android NDK
На Android нативний код викликається через JNI (Java Native Interface). Біндинг — це шар C/C++ функцій з іменами виду Java_com_example_MyClass_nativeMethod, які Dalvik/ART автоматично зв'язує з Java/Kotlin-методами, позначеними 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);
// виклик OpenCV або власної логіки
env->ReleaseByteArrayElements(pixels, input, JNI_ABORT);
// ...
}
Критичний момент — управління пам'яттю на межі JNI. GetByteArrayElements з прапором 0 копіює масив (безпечно, повільно). GetByteArrayElements з JNI_ABORT — не копіює зміни назад. Для продуктивної обробки зображень використовуємо GetDirectBufferAddress з ByteBuffer.allocateDirect() — це спільна пам'ять без копіювання.
CMakeLists.txt через Android NDK: вказуємо target_link_libraries для підключення передкомпільованої .a або .so бібліотеки. Для OpenCV — find_package(OpenCV REQUIRED) якщо собираємо з вихідних текстів, або ручне підключення libopencv_core.a + libopencv_imgproc.a через add_library(opencv STATIC IMPORTED). Розмір бінарника важливий: OpenCV статичне пов'язування додає 8–15 МБ на ABI. Використовуємо abiFilters "arm64-v8a", "x86_64" — видаляємо непотрібні ABI.
Обробка винятків у JNI. C++ виключення не проходять через JNI автоматично. Обертаємо в try/catch на C++-стороні, бросаємо Java-виключення через env->ThrowNew(env->FindClass("java/lang/RuntimeException"), message).
iOS: Objective-C мостування та Swift/C++ Interop
На iOS C-код підключається напрямо — Swift та Objective-C працюють в одному runtime з C. Для C++ потрібен Objective-C++ (.mm файли).
// ImageProcessorBridge.mm — обгортка Objective-C++
#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);
// обробка
NSData *result = ...;
return result;
}
@end
Swift викликає Objective-C через bridging header (-Bridging-Header.h). Не можна викликати C++ безпосередньо зі Swift до Swift 5.9, де з'явився експериментальний Swift/C++ Interop — дозволяє імпортувати C++ типи напрямо через import CxxModule. У production з Xcode 15 це вже робочий варіант для простих C++ API без шаблонів та віртуального наслідування.
XCFramework з нативною бібліотекою. Якщо підключаємо передкомпільовану C++ бібліотеку — собираємо .xcframework з lipo create для Device (arm64) та Simulator (arm64 + x86_64). Apple Silicon Simulator потребує arm64, Intel Mac — x86_64; fat binary через lipo об'єднує обидва.
OpenCV на iOS. Офіційний opencv2.framework (або xcframework) підключається через CocoaPods (pod 'OpenCV') або вручну. Розмір: ~160 МБ у debug, з bitcode linker вибирає тільки потрібні модулі. Для App Store важливо strip у Release-збірці.
Приклад. Додаток для обробки відеопотоку з камери в реальному часі (фільтри, розпізнавання обличчя): iOS — AVFoundation дає CMSampleBuffer → конвертація в cv::Mat через CVPixelBufferGetBaseAddress → OpenCV фільтр → відображення через MTLTexture (Metal). Android — Camera2 API → ImageReader з форматом YUV_420_888 → конвертація через libyuv в RGBA → OpenCV → SurfaceView. Біндинги написані на Objective-C++ (iOS) та JNI (Android). Продуктивність: обробка кадру 1920×1080 — 8–12 мс на iPhone 13, 15–22 мс на mid-range Android.
Збірка та інтеграція
CMake — кросс-платформена система збірки як для Android NDK так й для iOS (через CMake toolchain для iOS). Один CMakeLists.txt для нативної логіки, різні toolchain файли.
Для складних C++ бібліотек з autoconf/Makefile — configure && make запускається через cross-compilation toolchain NDK або iOS. Це більш трудомістко, але стандартна практика для OpenSSL, libsodium, FFmpeg.
Час реалізації
| Тип біндингу | Орієнтовні строки |
|---|---|
| Простата C бібліотека (crypto, compression) | 2–4 тижні |
| C++ бібліотека з нетривіальним API (OpenCV, FFmpeg) | 4–8 тижнів |
| Повна інтеграція з UI pipeline | 2–4 місяці |
Ціна розраховується індивідуально — залежить від складності API цільової бібліотеки та наявності існуючої документації.







