C++ en el desarrollo móvil: Android NDK, Unity y Unreal Engine

Autor: IT Sectr Publicado: 2026-02-10 Tiempo de lectura: 11 min

C++ es un lenguaje de programación multiparadigma con gestión manual de memoria, que combina programación procedural, orientada a objetos y genérica. En el desarrollo móvil, C++ se utiliza a través de Android NDK para portar bibliotecas y mediante los motores de juegos Unity y Unreal Engine para crear juegos multiplataforma. Según TIOBE (2026), C++ se encuentra entre los 5 lenguajes más populares entre los desarrolladores profesionales.

Puntos clave

  • C++ es un lenguaje de programación de sistemas utilizado en Android NDK, Unity y Unreal Engine
  • Android NDK permite compilar código C++ en bibliotecas .so nativas para procesadores ARM
  • Unreal Engine está completamente construido sobre C++, mientras que Unity usa C++ para plugins de bajo nivel
  • JNI (Java Native Interface) es el puente entre Java/Kotlin y C++ en Android
  • CMake y NDK Build son sistemas de compilación para proyectos C++ en plataformas móviles

¿Qué es C++?

C++ es un lenguaje de programación creado por Bjarne Stroustrup en 1985 como una extensión del lenguaje C con soporte de clases. C++ proporciona acceso directo a la memoria a través de punteros, metaprogramación de plantillas y herencia múltiple. Los estándares C++17 y C++20 agregaron corrutinas, conceptos y ranges.

A diferencia de Java y Kotlin, C++ no tiene recolector de basura — el desarrollador gestiona manualmente la asignación y liberación de memoria mediante los operadores new y delete. Esto proporciona control total sobre el rendimiento pero requiere disciplina. Según la Encuesta de Desarrolladores de JetBrains (2025), el 42% de los desarrolladores de C++ usan el lenguaje en la industria de los videojuegos.

Los estándares de C++ evolucionan cada tres años: C++11 (lambdas, auto, unique_ptr), C++14 (lambdas genéricas), C++17 (if constexpr, filesystem), C++20 (módulos, corrutinas, conceptos). Los compiladores Clang y GCC soportan todos los estándares actuales, y Android NDK usa Clang del toolchain LLVM.

Diferencias entre C++ y Java/Kotlin

La principal diferencia entre C++ y los lenguajes JVM es la gestión manual de memoria y la compilación directa a código máquina. Java y Kotlin funcionan sobre una máquina virtual con recolección automática de basura. El código C++ se compila en un binario nativo para una arquitectura específica — ARM, x86 o RISC-V.

CriterioC++Java / Kotlin
Gestión de memoriaManual (new/delete, RAII)Automática (recolector de basura)
CompilaciónCódigo máquina nativoBytecode JVM / ART
RendimientoMáximo (zero-cost abstractions)Alto con pausas de GC
Uso en desarrollo móvilNDK, juegos, bibliotecasAplicaciones UI, lógica de negocio
CompilaciónCMake, NDK Build, Gradle + NDKGradle, Maven
MultiplataformaCompilar para cada plataformaJVM / ART en todas partes

C++ en el desarrollo móvil: Android NDK

Android NDK (Native Development Kit) es un conjunto de herramientas de Google para escribir partes de aplicaciones Android en C y C++. El NDK incluye un toolchain basado en Clang, archivos de cabecera del sistema Android y bibliotecas de depuración y perfilado. La versión r27 (2025) soporta C++20 y usa LLVM 18.

El NDK compila código C++ en bibliotecas dinámicas .so para las arquitecturas ARM64, ARM32, x86 y x86_64. Una aplicación en Java o Kotlin carga estas bibliotecas mediante System.loadLibrary() y llama a funciones nativas a través de JNI. Según Google, el NDK se ha descargado más de 5 millones de veces.

Estructura de un proyecto con NDK

Un proyecto típico con Android NDK contiene la carpeta app/src/main/cpp/ con archivos fuente C++, CMakeLists.txt para la compilación y una clase Java con declaración de métodos nativos. Gradle conecta el NDK mediante el bloque externalNativeBuild en build.gradle.

cpp
// native-lib.cpp — método JNI simple para 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());
}

El código declara una función JNI con el nombre completo Java_com_example_app_MainActivity_stringFromJNI — esta es la convención de nomenclatura de JNI. La función recibe un puntero a JNIEnv (el entorno de ejecución) y jobject (la instancia de la clase que llama). env->NewStringUTF crea una cadena Java a partir de una cadena C++.

ABI y arquitecturas objetivo

Android soporta varios ABI (Application Binary Interface): arm64-v8a (dispositivos ARM de 64 bits, 99% de los smartphones modernos), armeabi-v7a (ARM de 32 bits, dispositivos antiguos), x86_64 (emuladores). El NDK permite compilar .so para cada arquitectura mediante filtros ABI en build.gradle.

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

C++ y los motores de juegos: Unity y Unreal Engine

C++ es el lenguaje principal de los motores de juegos. Unreal Engine usa C++ para todo el código del juego, mientras que Unity utiliza C++ en el núcleo del motor para renderizado y física. Incluso si un desarrollador escribe en C# en Unity, bajo el capó C++ gestiona los gráficos, el sonido y los cálculos físicos.

Unreal Engine: C++ como lenguaje principal

Unreal Engine está construido sobre C++ desde cero. El código de la lógica del juego se escribe en C++ utilizando macros UHT (Unreal Header Tool) para la integración con Blueprints — un sistema de scripting visual. Las clases heredan de tipos base AActor, UObject, UGameInstance con letras de prefijo U, A, F.

cpp
// Clase de personaje en Unreal Engine usando 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;
};

Las macros UCLASS() y UPROPERTY() son parte del sistema de reflexión de Unreal Engine. UHT (Unreal Header Tool) genera código C++ a partir de archivos de cabecera para serialización, blueprints y replicación de red. MoveSpeed se muestra en el editor mediante UPROPERTY(EditAnywhere).

Unity: C++ en plugins y SDK nativos

Unity usa C# para la lógica del juego, pero C++ se utiliza en Native Plugins — bibliotecas .so para Android y .bundle para iOS. A través de Android NDK se pueden conectar SDK de C++ para redes publicitarias, analítica o portar bibliotecas C++ de juegos de escritorio.

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);
    }
}

En este ejemplo, C# organiza una llamada a la función C++ ProcessFrame mediante P/Invoke. El atributo DllImport especifica el nombre de la biblioteca .so. La función C++ procesa el fotograma en tiempo real y devuelve el resultado. Este enfoque se utiliza para post-efectos y visión artificial.

JNI: interacción entre Java y C++

JNI (Java Native Interface) es el mecanismo estándar para llamar código C/C++ desde Java o Kotlin. En Android, JNI es la única forma de transferir datos entre la máquina virtual ART y una biblioteca nativa. Cada llamada JNI tiene sobrecarga, por lo que los datos deben transferirse en lotes en lugar de un campo a la vez.

JNIEnv es un puntero a la tabla de funciones JNI. env->FindClass carga una clase Java, env->GetMethodID obtiene un identificador de método, env->CallVoidMethod lo invoca. Para cadenas se usa GetStringUTFChars y ReleaseStringUTFChars. JNI también soporta referencias globales y débiles a objetos Java.

cpp
// Pasar array de bytes de C++ a Java mediante 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; // invertir bytes
    }

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

GetByteArrayElements obtiene un puntero al array de bytes Java. JNI_COMMIT en ReleaseByteArrayElements copia los cambios de vuelta al array Java sin liberar memoria. El procesamiento del bucle for se ejecuta en la CPU con el máximo rendimiento de C++ sin pausas de GC.

Gestión de memoria en JNI

El principal peligro de JNI son las fugas de referencias globales. Cada NewGlobalRef debe liberarse mediante DeleteGlobalRef. Las referencias locales (devueltas por FindClass, NewStringUTF) se liberan automáticamente al volver de la función nativa. Para llamadas intensivas, use PushLocalFrame / PopLocalFrame.

CMake y sistemas de compilación para C++ en Android

CMake es la herramienta de compilación principal para C++ en Android NDK. CMakeLists.txt describe los objetivos de compilación, bibliotecas y dependencias. Gradle invoca CMake a través de externalNativeBuild, pasando las rutas al NDK y al toolchain. Una alternativa es NDK Build basado en Android.mk y Application.mk.

CMake 3.22+ soporta presets (CMakePresets.json) para diferentes configuraciones: debug, release, profile con diferentes banderas de optimización. Para Android se usa el toolchain android.toolchain.cmake del NDK, suministrado automáticamente por Gradle durante la compilación.

cmake
# CMakeLists.txt para proyecto 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) crea una biblioteca .so. target_link_libraries enlaza las bibliotecas del sistema android (para JNI) y log (para __android_log_print). La biblioteca estática libjpeg.a se enlaza para trabajar con imágenes JPEG. CXX_STANDARD 20 habilita el soporte de C++20.

vcpkg y gestión de dependencias

vcpkg es un gestor de paquetes para C++ de Microsoft que soporta Android NDK como plataforma objetivo. A través de vcpkg se pueden instalar Boost, OpenCV, SQLite, nlohmann-json y otras bibliotecas compiladas para Android ABI. Vcpkg se integra con CMake mediante CMAKE_TOOLCHAIN_FILE.

Rendimiento de C++ en dispositivos móviles

C++ ofrece el máximo rendimiento en dispositivos móviles gracias a la compilación en código ARM nativo y la ausencia de recolector de basura. Según las pruebas de Google (Android Performance Patterns, 2024), el código JNI en C++ se ejecuta de 3 a 10 veces más rápido que el código Java equivalente para tareas con cálculos intensivos.

Factores clave del rendimiento de C++ en plataformas móviles: localidad de caché (disposición contigua de memoria), instrucciones SIMD NEON para ARM, comunicación JNI asíncrona mediante colas de mensajes. NEON es la extensión SIMD de ARM que procesa 128 bits de datos en una sola instrucción, indispensable para el procesamiento de audio, video e imágenes.

cpp
// Procesamiento SIMD de array mediante 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 carga 4 floats de la memoria en un registro NEON de 128 bits. vmulq_f32 multiplica los 4 elementos por 0.5 en un ciclo. vst1q_f32 guarda el resultado de vuelta. Sin SIMD, el mismo bucle realizaría 4 multiplicaciones secuencialmente — NEON proporciona hasta 4x de aceleración para estas operaciones.

OperaciónC++ (ms)Java/Kotlin (ms)Aceleración
Procesamiento de imagen 1920x108012453.75x
Transformada Rápida de Fourier (FFT)8344.25x
Cifrado AES-256 de bloque de 1MB3186x
Compresión de datos ZLIB5224.4x

Errores típicos al usar C++ en proyectos móviles

El primer error y el más peligroso son las fugas de memoria. Cada new debe tener un delete, cada new[] debe tener un delete[]. En dispositivos móviles con RAM limitada, cualquier fuga provoca OOM (Out Of Memory) y el cierre de la aplicación. Use RAII mediante punteros inteligentes: std::unique_ptr, std::shared_ptr, std::weak_ptr.

El segundo error es ignorar la compatibilidad ABI. Una biblioteca compilada para armeabi-v7a no se cargará en un dispositivo ARM64. Siempre especifique abiFilters en build.gradle y pruebe en dispositivos reales, no solo en el emulador x86_64. Use Android App Bundle para el filtrado automático de ABI.

El tercer error típico son las llamadas JNI frecuentes. Cada transición entre Java y C++ cuesta entre 50 y 100 ns. Si procesa un array de 10000 elementos uno por uno a través de JNI, la sobrecarga supera el trabajo útil. Pase arrays completos de una vez y procéselos en el lado de C++.

Problemas de concurrencia son otro error frecuente. C++ puede lanzar std::thread, pero solo se puede acceder a JNI desde hilos creados por Java. Para llamar métodos Java desde un hilo de C++, use AttachCurrentThread / DetachCurrentThread a través de JNI.

cpp
// Llamar correctamente a Java desde un hilo de C++
JavaVM *g_vm; // puntero global obtenido en 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();
    }
}

Preguntas frecuentes

¿Qué es Android NDK y por qué se necesita C++ en él?

Android NDK (Native Development Kit) es un conjunto de herramientas para escribir partes de aplicaciones en C o C++. Se utiliza para tareas críticas de rendimiento, portar bibliotecas C/C++ a Android e implementar código multiplataforma para Unity y Unreal Engine.

¿Qué juegos de Unity se escriben en C++?

En Unity, el código de la lógica del juego se escribe en C#, pero C++ se usa junto con Android NDK para plugins, aceleración hardware, portar bibliotecas C++ propias e integrar SDK nativos para publicidad y analítica.

¿Cómo configurar CMakeLists.txt para C++ en Android?

CMakeLists.txt describe archivos fuente, bibliotecas y banderas de compilación. La configuración mínima incluye add_library para compilar .so y target_link_libraries para enlazar el log de Android y otras bibliotecas del sistema.

¿Es obligatorio JNI en C++ para Android?

JNI (Java Native Interface) es la capa entre el código Java/Kotlin de una aplicación Android y la biblioteca C++. Si se llama C++ desde Java, JNI es obligatorio. Se puede escribir código C++ completamente a través de NDK, pero el punto de entrada suele ser una Activity de Java que llama a funciones nativas.

¿Cuándo está justificado C++ en lugar de Kotlin en el desarrollo móvil?

C++ está justificado para juegos, procesamiento de audio/video en tiempo real, visión artificial, criptografía, simulaciones físicas y portar bibliotecas de otras plataformas. Para una aplicación UI normal, Kotlin es más eficiente y sencillo.

Resumen

  • C++ es un lenguaje multiparadigma con gestión manual de memoria, utilizado en Android NDK, Unity y Unreal Engine para código de alto rendimiento
  • Android NDK compila C++ en bibliotecas .so para arquitecturas ARM con el toolchain Clang de LLVM
  • Unreal Engine está completamente construido sobre C++ con el sistema de reflexión UHT, Unity usa C++ en su núcleo de renderizado y física
  • JNI es el puente obligatorio entre Java/Kotlin y C++ en Android con la convención de nomenclatura Java___
  • CMake es el sistema de compilación principal para C++ en NDK, compatible con C++20 e integración con Gradle
  • NEON SIMD proporciona hasta 4x de aceleración en el procesamiento de datos en procesadores ARM mediante instrucciones vectoriales de 128 bits
  • Errores típicos: fugas de memoria, ABI incorrecto en abiFilters, llamadas JNI frecuentes y concurrencia sin AttachCurrentThread

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también