C++ în dezvoltarea mobilă: Android NDK, Unity și Unreal Engine

Autor: IT Sectr Publicat: 2026-02-10 Timp de citire: 11 min

C++ — un limbaj de programare multi-paradigmă cu gestionare manuală a memoriei, care combină programarea procedurală, orientată pe obiecte și generică. În dezvoltarea mobilă, C++ este utilizat prin Android NDK pentru portarea bibliotecilor și prin motoarele de jocuri Unity și Unreal Engine pentru crearea de jocuri cross-platform. Conform TIOBE (2026), C++ se află în top 5 limbaje după popularitate printre dezvoltatorii profesioniști.

Principalele puncte

  • C++ — un limbaj de programare de sistem utilizat în Android NDK, Unity și Unreal Engine
  • Android NDK permite compilarea codului C++ în biblioteci native .so pentru procesoare ARM
  • Unreal Engine este construit în întregime pe C++, iar Unity folosește C++ pentru pluginuri de nivel scăzut
  • JNI (Java Native Interface) — puntea între Java/Kotlin și C++ pe Android
  • CMake și NDK Build — sisteme de build pentru proiecte C++ pe platforme mobile

Ce este C++?

C++ — un limbaj de programare creat de Bjarne Stroustrup în 1985 ca o extensie a limbajului C cu suport pentru clase. C++ oferă acces direct la memorie prin pointeri, meta-programare cu template-uri și moștenire multiplă. Standardele C++17 și C++20 au adăugat corutine, concepte și ranges.

Spre deosebire de Java și Kotlin, C++ nu are garbage collector — dezvoltatorul gestionează manual alocarea și eliberarea memoriei prin operatorii new și delete. Acest lucru oferă control complet asupra performanței, dar necesită disciplină. Conform JetBrains Developer Survey (2025), 42% dintre dezvoltatorii C++ folosesc limbajul în industria jocurilor.

Standardele C++ evoluează la fiecare trei ani: C++11 (lambda, auto, unique_ptr), C++14 (lambda generalizate), C++17 (if constexpr, filesystem), C++20 (module, corutine, concepte). Compilatoarele Clang și GCC suportă toate standardele actuale, iar pentru Android NDK se folosește Clang din toolchain-ul LLVM.

Diferențele dintre C++ și Java și Kotlin

Principala diferență a C++ față de limbajele JVM — gestionarea manuală a memoriei și compilarea direct în cod mașină. Java și Kotlin rulează pe o mașină virtuală cu garbage collector automat. Codul C++ este compilat într-un fișier binar nativ pentru o arhitectură specifică — ARM, x86 sau RISC-V.

CriteriuC++Java / Kotlin
Gestionarea memorieiManuală (new/delete, RAII)Automată (Garbage Collector)
CompilareCod mașină nativBytecode JVM / ART
PerformanțăMaximă (zero-cost abstractions)Ridicată cu pauze GC
Utilizare în dezvoltarea mobilăNDK, jocuri, biblioteciAplicații UI, logică de business
BuildCMake, NDK Build, Gradle + NDKGradle, Maven
Cross-platformCompilare pentru fiecare platformăJVM / ART peste tot

C++ în dezvoltarea mobilă: Android NDK

Android NDK (Native Development Kit) — setul de instrumente Google pentru scrierea părților aplicației Android în C și C++. NDK include un toolchain bazat pe Clang, fișiere header de sistem Android, biblioteci pentru depanare și profilare. Versiunea r27 (2025) suportă C++20 și folosește LLVM 18.

NDK compilează codul C++ în biblioteci dinamice .so pentru arhitecturile ARM64, ARM32, x86 și x86_64. Aplicația Java sau Kotlin încarcă aceste biblioteci prin System.loadLibrary() și apelează funcțiile native prin JNI. Conform Google, NDK a fost descărcat de peste 5 milioane de ori.

Structura proiectului cu NDK

Un proiect tipic cu Android NDK conține folderul app/src/main/cpp/ cu fișiere sursă C++, CMakeLists.txt pentru build și o clasă Java cu declararea metodelor native. Gradle conectează NDK prin blocul externalNativeBuild din build.gradle.

cpp
// native-lib.cpp — o metodă JNI simplă pentru Android
#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_app_MainActivity_stringFromJNI(
    JNIEnv *env,
    jobject /*thiz*/) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

Codul declară o funcție JNI cu numele complet Java_com_example_app_MainActivity_stringFromJNI — aceasta este convenția de denumire JNI. Funcția primește un pointer către JNIEnv (mediul de execuție) și jobject (instanța clasei apelante). env->NewStringUTF creează un șir Java dintr-un șir C++.

ABI și arhitecturile țintă

Android suportă mai multe ABI (Application Binary Interface): arm64-v8a (dispozitive ARM pe 64 de biți, 99% din smartphone-urile moderne), armeabi-v7a (ARM pe 32 de biți, dispozitive vechi), x86_64 (emulatoare). NDK permite build-ul .so pentru fiecare arhitectură prin filtre ABI în build.gradle.

gradle
android {
    defaultConfig {
        ndk {
            abiFilters "arm64-v8a", "armeabi-v7a"
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.22.1"
        }
    }
}

C++ și motoarele de jocuri: Unity și Unreal Engine

C++ — limbajul principal al motoarelor de jocuri. Unreal Engine folosește C++ pentru întreg codul jocului, iar Unity utilizează C++ în nucleul motorului pentru randare și fizică. Chiar dacă dezvoltatorul scrie în C# în Unity, sub capotă C++ gestionează grafica, sunetul și calculele fizice.

Unreal Engine: C++ ca limbaj principal

Unreal Engine este construit pe C++ de la zero. Codul logicii jocului se scrie în C++ cu ajutorul macro-urilor UHT (Unreal Header Tool) pentru integrarea cu Blueprints — sistemul vizual de scripting. Clasele moștenesc de la tipurile de bază AActor, UObject, UGameInstance cu literele prefix U, A, F.

cpp
// Clasa personajului în Unreal Engine în C++
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MyCharacter.generated.h"

UCLASS()
class AMyCharacter : public ACharacter
{
    GENERATED_BODY()

public:
    AMyCharacter();

    virtual void BeginPlay() override;
    virtual void Tick(float DeltaTime) override;

    UPROPERTY(EditAnywhere, Category = "Movement")
    float MoveSpeed = 600.0f;

protected:
    void SetupPlayerInputComponent(UInputComponent *PlayerInputComponent) override;
};

Macro-urile UCLASS() și UPROPERTY() — fac parte din sistemul de reflecție al Unreal Engine. UHT (Unreal Header Tool) generează cod C++ din fișierele header pentru serializare, blueprinturi și replicare în rețea. MoveSpeed este afișat în editor prin UPROPERTY(EditAnywhere).

Unity: C++ în pluginuri și Native SDK

Unity folosește C# pentru logica jocului, dar C++ este utilizat în Native Plugins — biblioteci .so pentru Android și .bundle pentru iOS. Prin Android NDK se pot conecta SDK-uri C++ ale rețelelor de publicitate, analitică sau se poate porta o bibliotecă C++ din jocuri desktop.

csharp
using System.Runtime.InteropServices;
using UnityEngine;

public class NativeBridge : MonoBehaviour
{
    const string LIB_NAME = "native_plugin";

    [DllImport(LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
    private static extern int ProcessFrame(
        int width, int height,
        IntPtr pixelData
    );

    void Update()
    {
        int result = ProcessFrame(Screen.width, Screen.height, IntPtr.Zero);
        Debug.Log("Frame processed: " + result);
    }
}

În acest exemplu, C# face marshalingul apelului către funcția C++ ProcessFrame prin P/Invoke. Atributul DllImport specifică numele bibliotecii .so. Funcția C++ procesează cadrul în timp real și returnează rezultatul. Această abordare este folosită pentru post-efecte și viziune computerizată.

JNI: interacțiunea Java și C++

JNI (Java Native Interface) — mecanismul standard pentru apelarea codului C/C++ din Java sau Kotlin. În Android, JNI este singura modalitate de a transmite date între mașina virtuală ART și biblioteca nativă. Fiecare apel JNI are un overhead, de aceea datele sunt transmise în pachete, nu câte un câmp.

JNIEnv — un pointer către tabela funcțiilor JNI. env->FindClass încarcă o clasă Java, env->GetMethodID obține identificatorul metodei, env->CallVoidMethod o apelează. Pentru șiruri se folosește GetStringUTFChars și ReleaseStringUTFChars. JNI suportă, de asemenea, referințe globale și slabe la obiecte Java.

cpp
// Transmiterea array-ului de bytes din C++ în Java prin JNI
extern "C" JNIEXPORT void JNICALL
Java_com_example_app_ImageProcessor_processArray(
    JNIEnv *env, jobject /*thiz*/,
    jbyteArray input, jint length) {

    jbyte *buffer = env->GetByteArrayElements(input, nullptr);
    jsize size = env->GetArrayLength(input);

    for (jsize i = 0; i < size; ++i) {
        buffer[i] = buffer[i] ^ 0xFF; // inversăm bytes
    }

    env->ReleaseByteArrayElements(input, buffer, JNI_COMMIT);
}

GetByteArrayElements obține un pointer la array-ul de bytes Java. JNI_COMMIT în ReleaseByteArrayElements copiază modificările înapoi în array-ul Java fără a elibera memoria. Procesarea în buclă for se execută pe CPU cu performanța maximă a C++ fără pauze GC.

Gestionarea memoriei în JNI

Principalul pericol al JNI — scurgeri de referințe globale. Fiecare NewGlobalRef trebuie eliberat prin DeleteGlobalRef. Referințele locale (returnate de FindClass, NewStringUTF) sunt șterse automat la revenirea din funcția native. Pentru apeluri intensive folosiți PushLocalFrame / PopLocalFrame.

CMake și sistemele de build pentru C++ pe Android

CMake — instrumentul principal de build pentru C++ în Android NDK. CMakeLists.txt descrie țintele de build, bibliotecile și dependențele. Gradle apelează CMake prin externalNativeBuild, transmițând căile către NDK și toolchain. Alternativa — NDK Build bazat pe Android.mk și Application.mk.

CMake 3.22+ suportă preseturi (CMakePresets.json) pentru diferite configurații: debug, release, profile cu diferite flaguri de optimizare. Pentru Android se folosește toolchain-ul android.toolchain.cmake din NDK, substituit automat de Gradle la build.

cmake
# CMakeLists.txt pentru proiectul Android NDK
cmake_minimum_required(VERSION 3.22)
project("native-lib")

add_library(
    native-lib
    SHARED
    src/main/cpp/native-lib.cpp
    src/main/cpp/image_utils.cpp
)

target_include_directories(
    native-lib PRIVATE
    src/main/cpp/include
)

target_link_libraries(
    native-lib
    android
    log
    ${CMAKE_SOURCE_DIR}/libs/libjpeg.a
)

set_target_properties(
    native-lib PROPERTIES
    CXX_STANDARD 20
    CXX_STANDARD_REQUIRED ON
)

add_library(SHARED) creează o bibliotecă .so. target_link_libraries conectează bibliotecile de sistem android (pentru JNI) și log (pentru __android_log_print). Biblioteca statică libjpeg.a este linkată pentru lucrul cu imagini JPEG. CXX_STANDARD 20 activează suportul C++20.

vcpkg și gestionarea dependențelor

vcpkg — managerul de pachete pentru C++ de la Microsoft, care suportă Android NDK ca platformă țintă. Prin vcpkg se pot instala Boost, OpenCV, SQLite, nlohmann-json și alte biblioteci compilate pentru Android ABI. Vcpkg se integrează cu CMake prin CMAKE_TOOLCHAIN_FILE.

Performanța C++ pe dispozitive mobile

C++ oferă performanță maximă pe dispozitivele mobile datorită compilării în cod nativ ARM și absenței garbage collector-ului. Conform testelor Google (Android Performance Patterns, 2024), codul JNI în C++ se execută de 3–10 ori mai rapid decât codul Java echivalent pentru sarcini cu calcule intensive.

Factorii cheie ai performanței C++ pe platformele mobile: localitatea cache (plasarea datelor în memorie continuă), instrucțiunile SIMD NEON pentru ARM, lucrul asincron cu JNI prin cozi de mesaje. NEON — extensia SIMD a ARM, care permite procesarea a 128 de biți de date într-o singură instrucțiune, indispensabilă pentru procesarea audio, video și imagini.

cpp
// Procesarea SIMD a array-ului prin NEON intrinsics
#include <arm_neon.h>

void process_audio_neon(float *data, size_t n) {
    for (size_t i = 0; i < n; i += 4) {
        float32x4_t vec = vld1q_f32(&data[i]);
        float32x4_t result = vmulq_f32(vec, vdupq_n_f32(0.5f));
        vst1q_f32(&data[i], result);
    }
}

vld1q_f32 încarcă 4 float din memorie într-un registru NEON de 128 de biți. vmulq_f32 înmulțește toate cele 4 elemente cu 0.5 într-un singur ciclu. vst1q_f32 salvează rezultatul înapoi. Fără SIMD, aceeași buclă ar executa 4 înmulțiri secvențial — NEON oferă o accelerare de până la 4x pentru astfel de operații.

OperațieC++ (ms)Java/Kotlin (ms)Accelerare
Procesarea imaginii 1920x108012453.75x
Transformarea Fourier rapidă (FFT)8344.25x
Criptarea AES-256 a unui bloc de 1MB3186x
Comprimarea datelor ZLIB5224.4x

Erori tipice la utilizarea C++ în proiecte mobile

Prima și cea mai periculoasă greșeală — scurgerea de memorie. Fiecare new trebuie să aibă un delete, fiecare new[] — delete[]. Pe dispozitivele mobile cu RAM limitată, orice scurgere duce la OOM (Out Of Memory) și la căderea aplicației. Folosiți RAII prin pointeri inteligenți: std::unique_ptr, std::shared_ptr, std::weak_ptr.

A doua greșeală — ignorarea compatibilității ABI. O bibliotecă compilată pentru armeabi-v7a nu se va încărca pe un dispozitiv ARM64. Specificați întotdeauna abiFilters în build.gradle și testați pe dispozitive reale, nu doar pe emulatorul x86_64. Folosiți Android App Bundle pentru filtrarea automată ABI.

A treia greșeală tipică — apeluri frecvente JNI. Fiecare tranziție între Java și C++ costă aproximativ 50–100 ns. Dacă procesați un array de 10000 de elemente unul câte unul prin JNI, overhead-ul va depăși munca utilă. Transmiteți datele ca array-uri întregi și procesați-le pe partea C++.

Problemele cu multi-threading-ul — încă o greșeală frecventă. C++ poate porni std::thread, dar accesul la JNI este posibil doar din thread-ul creat de Java. Pentru a apela metode Java din thread-ul C++, folosiți AttachCurrentThread / DetachCurrentThread prin JNI.

cpp
// Apelarea corectă a Java din thread-ul C++
JavaVM *g_vm; // pointer global, obținut la JNI_OnLoad

void background_task() {
    JNIEnv *env;
    jint res = g_vm->AttachCurrentThread(&env, nullptr);
    if (res == JNI_OK) {
        jclass clazz = env->FindClass("com/example/App");
        jmethodID mid = env->GetStaticMethodID(clazz, "onProgress", "(I)V");
        env->CallStaticVoidMethod(clazz, mid, 100);
        g_vm->DetachCurrentThread();
    }
}

Întrebări frecvente

Ce este Android NDK și de ce se folosește C++ în el?

Android NDK (Native Development Kit) — un set de instrumente pentru scrierea părților aplicației în C sau C++. Este utilizat pentru sarcini critice pentru performanță, portarea bibliotecilor C/C++ pe Android și implementarea codului cross-platform Unity și Unreal Engine.

Ce jocuri Unity se scriu în C++?

În Unity, codul logicii jocului se scrie în C#, dar C++ este folosit împreună cu Android NDK pentru pluginuri, lucrul cu accelerarea hardware, portarea bibliotecilor proprii C++ și integrarea SDK-urilor native pentru publicitate și analitică.

Cum se configurează CMakeLists.txt pentru C++ pe Android?

CMakeLists.txt descrie fișierele sursă, bibliotecile și flagurile de compilare. Configurația minimă include add_library pentru build-ul .so și target_link_libraries pentru conectarea Android log și a altor biblioteci de sistem.

JNI în C++ este obligatoriu pentru Android?

JNI (Java Native Interface) — stratul intermediar între codul Java/Kotlin al aplicației Android și biblioteca C++. Dacă C++ este apelat din Java, JNI este obligatoriu. Se poate scrie cod C++ complet prin NDK, dar punctul de intrare este de obicei o activitate Java care apelează funcții native.

Când este justificat C++ în loc de Kotlin în dezvoltarea mobilă?

C++ este justificat pentru jocuri, procesarea audio/video în timp real, viziune computerizată, criptografie, simulări fizice și portarea bibliotecilor de pe alte platforme. Pentru o aplicație UI obișnuită, Kotlin este mai eficient și mai simplu.

Rezumat

  • C++ — un limbaj multi-paradigmă cu gestionare manuală a memoriei, utilizat în Android NDK, Unity și Unreal Engine pentru cod de înaltă performanță
  • Android NDK compilează C++ în biblioteci .so pentru arhitecturi ARM cu toolchain-ul Clang din LLVM
  • Unreal Engine este construit în întregime pe C++ cu sistemul de reflecție UHT, Unity folosește C++ în nucleul de randare și fizică
  • JNI — puntea obligatorie între Java/Kotlin și C++ pe Android cu convenția de denumire Java___
  • CMake — sistemul principal de build pentru C++ în NDK, care suportă C++20 și integrarea cu Gradle
  • NEON SIMD oferă până la 4x accelerare a procesării datelor pe procesoare ARM prin instrucțiuni vectoriale de 128 de biți
  • Erori tipice: scurgeri de memorie, ABI incorect în abiFilters, apeluri frecvente JNI și multi-threading fără AttachCurrentThread

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și