Android'de C/C++: Kullanım Alanları ve Pratik NDK Bağlantısı

Kerem Aydın·7 Temmuz 2026·⏱3 dk

Android'de C/C++, maksimum performans gerektiren modüller için kullanılır: grafikler, kodekler, ses/video işleme, ML çıkarımı, kriptografi ve düşük seviyeli ağ yardımcı programları. NDK, Android Studio (SDK Manager → NDK) aracılığıyla bağlanır, ardından CMake/ndk-build yapılandırılır, JNI sarmalayıcıları yazılır ve Java/Kotlin'e yüklenen yerel (native) kitaplık derlenir.

C/C++ Kullanmanın Mantıklı Olduğu Durumlar

  • Grafikler ve oyunlar: OpenGL/Vulkan üzerinden renderlama, fizik, gölgelendiriciler — GPU'ya doğrudan erişim ve düşük gecikme.
  • Multimedya: Kod çözücüler/kodlayıcılar (FFmpeg), DSP algoritmaları ve gerçek zamanlı ses — daha düşük enerji tüketimi ve gecikmeler.
  • Makine öğrenimi: TensorFlow Lite/ONNX içindeki lineer cebir çekirdekleri ve SIMD optimizasyonları.
  • Kripto ve ağ proxy'leri: Bellek kontrolü, soket işlemleri, performans.
  • Eski (legacy) kitaplıkların veya çapraz platform kodunun yeniden kullanılması (TDLib, OpenSSL vb.).

NDK geliştirmeyi karmaşıklaştırır: hata ayıklama daha yavaştır, APK boyutu artar, birden fazla ABI'yi (arm64-v8a, armeabi-v7a, x86_64) desteklemeniz gerekir. Profil oluşturma yapmadan optimizasyon amacıyla NDK'yı bağlamayın.

NDK'ya geçiş için kriterler:

  • Dar profilde CPU darboğazı döngülerde (>10^6 yineleme/saniye) veya büyük arabelleklerle çalışırken görülür.
  • Enerji tüketimi optimizasyonu veya mevcut bir C/C++ kitaplığına erişim gerekir.
  • Sistem özelliklerine veya donanım API'sine doğrudan erişim gereklidir.

NDK'yı Bağlama: Hızlı Adım Adım Kılavuz

  1. NDK'yı yükleyin:
    • Android Studio → SDK Manager → SDK Tools → "NDK (side-by-side)" seçeneğini işaretleyin ve sürümü yükleyin (modern Android'ler için 26+ önerilir).
  2. build.gradle yapılandırması (module: app):
android {
  defaultConfig {
    externalNativeBuild {
      cmake {
        cppFlags "-std=c++17"
      }
      ndk {
        abiFilters "arm64-v8a", "armeabi-v7a"
      }
    }
  }
  externalNativeBuild {
    cmake {
      path "src/main/cpp/CMakeLists.txt"
    }
  }
}
  1. Örnek CMakeLists.txt (src/main/cpp/CMakeLists.txt):
cmake_minimum_required(VERSION 3.22)
project(myndk)
add_library(myndk SHARED native-lib.cpp)
find_library(log-lib log)
target_link_libraries(myndk ${log-lib})
  1. Örnek native-lib.cpp:
#include <jni.h>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapp_MainActivity_stringFromJNI(JNIEnv* env, jobject /* this */) {
  return env->NewStringUTF("Hello from C++");
}
  1. Java/Kotlin çağrısı ve kitaplık yükleme:
class MainActivity : AppCompatActivity() {
  external fun stringFromJNI(): String
  companion object { init { System.loadLibrary("myndk") } }
}
  1. Derleme ve test: Projeyi derleyin, ABI uyumluluğunu gerçek bir cihazda ve/veya ARM içeren emülatörde kontrol edin.

Karmaşık kripto/ML görevleri için önce hazır AAR'ları (TensorFlow Lite, kamera kitaplığı) kontrol edin, bu haftalarca geliştirme süresinden tasarruf sağlar.

Derleme Araçları: CMake vs ndk-build

  • CMake: Google tarafından önerilir, çapraz platformludur, modern C++ özelliklerini ve Gradle entegrasyonunu destekler. Yeni ve karmaşık projeler için uygundur.
  • ndk-build (Make): Eski projeler ve hızlı prototipler için daha basittir, ancak daha az esnektir ve kademeli olarak eskimektedir.

Seçim: Yeni bir projeye başlıyorsanız CMake kullanın.

En İyi Uygulamalar ve Hata Ayıklama

  • Sık JNI çağrılarını en aza indirin: Çok sayıda küçük çağrı yerine büyük veri blokları (diziler) gönderin.
  • ABI yönetimi: arm64 ve armeabi-v7a üzerinde test edin, APK boyutunu düşürmek için gereksiz ABI'leri hariç tutun.
  • Hata ayıklama araçları: Android Studio'da LLDB, test derlemeleri için android:debuggable özelliğini etkinleştirin.
  • Bellek: AddressSanitizer (ASan) ve statik analiz araçlarını kullanın, bellek sızıntılarını takip edin.
  • Profil oluşturma: Systrace, Perfetto, Android Studio Profiler — yerel kodun CPU ve pil üzerindeki etkisini ölçün.

Sık Yapılan Hatalar

  • extern "C" unutuldu → JNI sembolü bulamaz.
  • Yanlış JNI imzası (paket/sınıf adı) → UnsatisfiedLinkError.
  • Eksik ABI dosyaları → uygulama diğer mimarilerde çöker.
  • Sık yapılan küçük JNI çağrıları → performans düşüşü.
  • Kontrol edilmemiş işaretçiler/C++ bellek sızıntıları → kritik hatalar.

SSS

  • Tüm kodu C++'a çevirmek gerekir mi? Hayır. Kullanıcı arayüzünü ve iş mantığını Kotlin/Java'da bırakın, yalnızca performans darboğazlarını C/C++'a taşıyın.
  • ABI seti nasıl seçilir? Çoğu uygulama için arm64-v8a ve armeabi-v7a yeterlidir; x86_64'ü yalnızca özel gereksinimler için ekleyin.
  • APK boyutu nasıl küçültülür? Sembol temizleme (strip), kitaplık birleştirme, gereksiz ABI'leri hariç tutma, ABI bazında split APKs kullanma.

Basit bir "hello-jni" ile başlayın, profil oluşturun, ardından kritik bölümleri NDK'ya taşıyın. C/C++'ın doğru entegrasyonu, gerçekten ihtiyaç duyulan yerlerde performansta önemli kazanç sağlayacaktır.