C++ در توسعه موبایل: Android NDK، Unity و Unreal Engine

نویسنده: IT Sectr منتشر شده: 2026-02-10 زمان مطالعه: 11 دقیقه

C++ — یک زبان برنامه‌نویسی چندالگویی با مدیریت دستی حافظه است که برنامه‌نویسی رویه‌ای، شیءگرا و عمومی را ترکیب می‌کند. در توسعه موبایل، C++ از طریق Android NDK برای انتقال کتابخانه‌ها و از طریق موتورهای بازی Unity و Unreal Engine برای ایجاد بازی‌های چندسکویی استفاده می‌شود. طبق TIOBE (2026)، C++ در بین پنج زبان محبوب در میان توسعه‌دهندگان حرفه‌ای قرار دارد.

نکات اصلی

  • C++ — زبان برنامه‌نویسی سیستمی مورد استفاده در Android NDK، Unity و Unreal Engine
  • Android NDK امکان کامپایل کد C++ به کتابخانه‌های native .so برای پردازنده‌های ARM را فراهم می‌کند
  • Unreal Engine کاملاً بر روی C++ ساخته شده است و Unity از C++ برای پلاگین‌های سطح پایین استفاده می‌کند
  • JNI (Java Native Interface) — پل ارتباطی بین Java/Kotlin و C++ در Android
  • CMake و NDK Build — سیستم‌های ساخت برای پروژه‌های C++ در سکوهای موبایل

C++ چیست؟

C++ — زبان برنامه‌نویسی ایجاد شده توسط بیارنه استراستروپ در سال ۱۹۸۵ به عنوان توسعه زبان C با پشتیبانی از کلاس‌ها. C++ دسترسی مستقیم به حافظه را از طریق اشاره‌گرها، فرابرنامه‌نویسی قالبی و وراثت چندگانه فراهم می‌کند. استانداردهای C++17 و C++20 کوروتین‌ها، کانسپت‌ها و رنج‌ها را اضافه کردند.

برخلاف Java و Kotlin، C++ زباله‌روب ندارد — توسعه‌دهنده به صورت دستی تخصیص و آزادسازی حافظه را از طریق عملگرهای new و delete مدیریت می‌کند. این امر کنترل کامل بر عملکرد را فراهم می‌کند اما نیازمند انضباط است. طبق JetBrains Developer Survey (2025)، ۴۲٪ از توسعه‌دهندگان C++ از این زبان در صنعت بازی استفاده می‌کنند.

استانداردهای C++ هر سه سال یکبار تکامل می‌یابند: C++11 (لامبداها، auto، unique_ptr)، C++14 (لامبداهای عمومی)، C++17 (if constexpr، filesystem)، C++20 (ماژول‌ها، کوروتین‌ها، کانسپت‌ها). کامپایلرهای Clang و GCC از همه استانداردهای فعلی پشتیبانی می‌کنند و برای Android NDK از Clang از زنجیره ابزار LLVM استفاده می‌شود.

تفاوت‌های C++ با Java و Kotlin

تفاوت اصلی C++ با زبان‌های JVM — مدیریت دستی حافظه و کامپایل مستقیم به کد ماشین است. Java و Kotlin روی ماشین مجازی با جمع‌آوری خودکار زباله کار می‌کنند. کد C++ به یک فایل باینری بومی برای معماری خاص — ARM، x86 یا RISC-V کامپایل می‌شود.

معیارC++Java / Kotlin
مدیریت حافظهدستی (new/delete, RAII)خودکار (Garbage Collector)
کامپایلکد ماشین بومیبایت‌کد JVM / ART
عملکردحداکثر (zero-cost abstractions)بالا با توقف‌های GC
استفاده در توسعه موبایلNDK، بازی‌ها، کتابخانه‌هابرنامه‌های UI، منطق تجاری
ساختCMake، NDK Build، Gradle + NDKGradle، Maven
چندسکوییکامپایل برای هر سکوJVM / ART همه‌جا

C++ در توسعه موبایل: Android NDK

Android NDK (Native Development Kit) — مجموعه ابزارهای Google برای نوشتن بخش‌هایی از برنامه Android به زبان C و C++. NDK شامل زنجیره ابزار مبتنی بر Clang، فایل‌های هدر سیستمی Android، کتابخانه‌های اشکال‌زدایی و پروفایلینگ است. نسخه r27 (2025) از C++20 پشتیبانی می‌کند و از LLVM 18 استفاده می‌کند.

NDK کد C++ را به کتابخانه‌های پویا .so برای معماری‌های ARM64، ARM32، x86 و x86_64 کامپایل می‌کند. برنامه Java یا Kotlin این کتابخانه‌ها را از طریق System.loadLibrary() بارگذاری می‌کند و توابع native را از طریق JNI فراخوانی می‌کند. طبق Google، NDK بیش از ۵ میلیون بار دانلود شده است.

ساختار پروژه با NDK

یک پروژه معمولی با Android NDK شامل پوشه app/src/main/cpp/ با فایل‌های منبع C++، CMakeLists.txt برای ساخت و کلاس Java با اعلام متدهای native است. Gradle NDK را از طریق بلوک externalNativeBuild در build.gradle متصل می‌کند.

cpp
// native-lib.cpp — یک متد ساده JNI برای 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());
}

کد یک تابع JNI با نام کامل Java_com_example_app_MainActivity_stringFromJNI را اعلام می‌کند — این قرارداد نام‌گذاری JNI است. تابع یک اشاره‌گر به JNIEnv (محیط اجرا) و jobject (نمونه کلاس فراخوان) را دریافت می‌کند. env->NewStringUTF یک رشته Java از رشته C++ ایجاد می‌کند.

ABI و معماری‌های هدف

Android از چندین ABI (Application Binary Interface) پشتیبانی می‌کند: arm64-v8a (دستگاه‌های ۶۴ بیتی ARM، ۹۹٪ گوشی‌های هوشمند مدرن)، armeabi-v7a (ARM ۳۲ بیتی، دستگاه‌های قدیمی)، x86_64 (شبیه‌سازها). NDK امکان ساخت .so برای هر معماری را از طریق فیلترهای ABI در build.gradle فراهم می‌کند.

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

C++ و موتورهای بازی: Unity و Unreal Engine

C++ — زبان اصلی موتورهای بازی است. Unreal Engine از C++ برای تمام کد بازی استفاده می‌کند و Unity از C++ در هسته موتور برای رندرینگ و فیزیک استفاده می‌کند. حتی اگر توسعه‌دهنده در Unity به زبان C# بنویسد، در پشت صحنه C++ گرافیک، صدا و محاسبات فیزیکی را مدیریت می‌کند.

Unreal Engine: C++ به عنوان زبان اصلی

Unreal Engine از پایه بر روی C++ ساخته شده است. کد منطق بازی به زبان C++ با استفاده از ماکروهای UHT (Unreal Header Tool) برای یکپارچه‌سازی با Blueprints — سیستم بصری اسکریپت‌نویسی نوشته می‌شود. کلاس‌ها از انواع پایه AActor، UObject، UGameInstance با حروف پیشوند U، A، F ارث‌بری می‌کنند.

cpp
// کلاس کاراکتر در Unreal Engine به زبان 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;
};

ماکروهای UCLASS() و UPROPERTY() — بخشی از سیستم بازتاب Unreal Engine هستند. UHT (Unreal Header Tool) کد C++ را از فایل‌های هدر برای سریال‌سازی، بلوپرینت‌ها و تکرار شبکه تولید می‌کند. MoveSpeed از طریق UPROPERTY(EditAnywhere) در ویرایشگر نمایش داده می‌شود.

Unity: C++ در پلاگین‌ها و Native SDK

Unity از C# برای منطق بازی استفاده می‌کند، اما C++ در Native Plugins — کتابخانه‌های .so برای Android و .bundle برای iOS به کار می‌رود. از طریق Android NDK می‌توان C++ SDK شبکه‌های تبلیغاتی، تجزیه و تحلیل را متصل کرد یا کتابخانه C++ را از بازی‌های رومیزی منتقل کرد.

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

در این مثال، C# فراخوانی تابع C++ ProcessFrame را از طریق P/Invoke مارشال می‌کند. ویژگی DllImport نام کتابخانه .so را مشخص می‌کند. تابع C++ فریم را در زمان واقعی پردازش می‌کند و نتیجه را برمی‌گرداند. چنین رویکردی برای پس‌اثرها و بینایی کامپیوتری استفاده می‌شود.

JNI: تعامل Java و C++

JNI (Java Native Interface) — مکانیزم استاندارد برای فراخوانی کد C/C++ از Java یا Kotlin است. در Android، JNI تنها راه انتقال داده بین ماشین مجازی ART و کتابخانه بومی است. هر فراخوانی JNI سربار دارد، بنابراین داده‌ها به صورت بسته‌ای و نه تک‌تک فیلدها منتقل می‌شوند.

JNIEnv — اشاره‌گری به جدول توابع JNI است. env->FindClass کلاس Java را بارگذاری می‌کند، env->GetMethodID شناسه متد را می‌گیرد، env->CallVoidMethod آن را فراخوانی می‌کند. برای رشته‌ها از GetStringUTFChars و ReleaseStringUTFChars استفاده می‌شود. JNI همچنین از ارجاع‌های سراسری و ضعیف به اشیاء Java پشتیبانی می‌کند.

cpp
// انتقال آرایه بایت از C++ به Java از طریق 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; // بایت‌ها را معکوس می‌کنیم
    }

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

GetByteArrayElements اشاره‌گری به آرایه بایت Java می‌گیرد. JNI_COMMIT در ReleaseByteArrayElements تغییرات را بدون آزادسازی حافظه به آرایه Java برمی‌گرداند. پردازش حلقه for روی CPU با حداکثر عملکرد C++ بدون توقف‌های GC انجام می‌شود.

مدیریت حافظه در JNI

خطر اصلی JNI — نشت ارجاع‌های سراسری است. هر NewGlobalRef باید از طریق DeleteGlobalRef آزاد شود. ارجاع‌های محلی (بازگشتی از FindClass، NewStringUTF) به طور خودکار هنگام بازگشت از تابع native حذف می‌شوند. برای فراخوانی‌های فشرده از PushLocalFrame / PopLocalFrame استفاده کنید.

CMake و سیستم‌های ساخت C++ برای Android

CMake — ابزار اصلی ساخت برای C++ در Android NDK است. CMakeLists.txt اهداف ساخت، کتابخانه‌ها و وابستگی‌ها را توصیف می‌کند. Gradle CMake را از طریق externalNativeBuild فراخوانی می‌کند و مسیرهای NDK و زنجیره ابزار را ارسال می‌کند. جایگزین — NDK Build مبتنی بر Android.mk و Application.mk.

CMake 3.22+ از پریست‌ها (CMakePresets.json) برای تنظیمات مختلف پشتیبانی می‌کند: debug، release، profile با پرچم‌های بهینه‌سازی متفاوت. برای Android از زنجیره ابزار android.toolchain.cmake از NDK استفاده می‌شود که توسط Gradle در هنگام ساخت به طور خودکار جایگزین می‌شود.

cmake
# CMakeLists.txt برای پروژه 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) یک کتابخانه .so ایجاد می‌کند. target_link_libraries کتابخانه‌های سیستمی android (برای JNI) و log (برای __android_log_print) را متصل می‌کند. کتابخانه ایستا libjpeg.a برای کار با تصاویر JPEG لینک می‌شود. CXX_STANDARD 20 پشتیبانی C++20 را فعال می‌کند.

vcpkg و مدیریت وابستگی‌ها

vcpkg — مدیر بسته برای C++ از مایکروسافت که از Android NDK به عنوان سکوی هدف پشتیبانی می‌کند. از طریق vcpkg می‌توان Boost، OpenCV، SQLite، nlohmann-json و سایر کتابخانه‌های کامپایل شده برای Android ABI را نصب کرد. Vcpkg از طریق CMAKE_TOOLCHAIN_FILE با CMake یکپارچه می‌شود.

عملکرد C++ در دستگاه‌های موبایل

C++ به لطف کامپایل به کد بومی ARM و عدم وجود زباله‌روب، حداکثر عملکرد را در دستگاه‌های موبایل فراهم می‌کند. طبق آزمایش‌های Google (Android Performance Patterns، ۲۰۲۴)، کد JNI در C++ برای وظایف با محاسبات فشرده ۳ تا ۱۰ برابر سریع‌تر از کد معادل Java اجرا می‌شود.

عوامل کلیدی عملکرد C++ در سکوهای موبایل: محلی‌بودن کش (قرارگیری داده‌ها در حافظه پیوسته)، دستورالعمل‌های SIMD NEON برای ARM، کار ناهمگام با JNI از طریق صف‌های پیام. NEON — افزونه SIMD ARM که امکان پردازش ۱۲۸ بیت داده در یک دستورالعمل را فراهم می‌کند، برای پردازش صدا، ویدئو و تصاویر ضروری است.

cpp
// پردازش آرایه SIMD از طریق 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 ۴ عدد float را از حافظه به ثبات ۱۲۸ بیتی NEON بارگذاری می‌کند. vmulq_f32 هر ۴ عنصر را در یک سیکل در ۰.۵ ضرب می‌کند. vst1q_f32 نتیجه را برمی‌گرداند. بدون SIMD همان حلقه ۴ ضرب را متوالی انجام می‌داد — NEON برای چنین عملیاتی تا ۴x شتاب می‌دهد.

عملیاتC++ (ms)Java/Kotlin (ms)شتاب
پردازش تصویر 1920x1080۱۲۴۵۳.۷۵x
تبدیل سریع فوریه (FFT)۸۳۴۴.۲۵x
رمزگذاری AES-256 بلوک ۱MB۳۱۸۶x
فشرده‌سازی داده ZLIB۵۲۲۴.۴x

اشتباهات رایج در استفاده از C++ در پروژه‌های موبایل

اولین و خطرناک‌ترین اشتباه — نشت حافظه. هر new باید delete داشته باشد، هر new[] — delete[]. در دستگاه‌های موبایل با RAM محدود، هر نشتی منجر به OOM (Out Of Memory) و سقوط برنامه می‌شود. از RAII از طریق اشاره‌گرهای هوشمند استفاده کنید: std::unique_ptr، std::shared_ptr، std::weak_ptr.

دومین اشتباه — نادیده گرفتن سازگاری ABI. کتابخانه‌ای که برای armeabi-v7a کامپایل شده، روی دستگاه ARM64 بارگذاری نمی‌شود. همیشه abiFilters را در build.gradle مشخص کنید و روی دستگاه‌های واقعی تست کنید، نه فقط شبیه‌ساز x86_64. از Android App Bundle برای فیلتر خودکار ABI استفاده کنید.

سومین اشتباه رایج — فراخوانی‌های مکرر JNI. هر انتقال بین Java و C++ حدود ۵۰–۱۰۰ ns هزینه دارد. اگر آرایه‌ای از ۱۰۰۰۰ عنصر را یکی یکی از طریق JNI پردازش کنید، سربار از کار مفید بیشتر می‌شود. داده‌ها را به صورت آرایه‌های کامل منتقل کنید و در سمت C++ پردازش کنید.

مشکلات چندنخی — یکی دیگر از اشتباهات رایج. C++ می‌تواند std::thread را راه‌اندازی کند، اما دسترسی به JNI فقط از نخی که توسط Java ایجاد شده امکان‌پذیر است. برای فراخوانی متدهای Java از نخ C++ از AttachCurrentThread / DetachCurrentThread از طریق JNI استفاده کنید.

cpp
// فراخوانی صحیح Java از نخ C++
JavaVM *g_vm; // اشاره‌گر سراسری، دریافت شده در 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();
    }
}

سوالات متداول

Android NDK چیست و چرا در آن از C++ استفاده می‌شود؟

Android NDK (Native Development Kit) — مجموعه ابزاری برای نوشتن بخش‌هایی از برنامه به زبان C یا C++. از آن برای وظایف حیاتی از نظر عملکرد، انتقال کتابخانه‌های C/C++ به Android و پیاده‌سازی کد چندسکویی Unity و Unreal Engine استفاده می‌شود.

کدام بازی‌های Unity به زبان C++ نوشته می‌شوند؟

در Unity کد منطق بازی به زبان C# نوشته می‌شود، اما C++ در ترکیب با Android NDK برای پلاگین‌ها، کار با شتاب‌دهی سخت‌افزاری، انتقال کتابخانه‌های اختصاصی C++ و یکپارچه‌سازی SDKهای بومی برای تبلیغات و تحلیل استفاده می‌شود.

چگونه CMakeLists.txt را برای C++ در Android پیکربندی کنیم؟

CMakeLists.txt فایل‌های منبع، کتابخانه‌ها و پرچم‌های کامپایل را توصیف می‌کند. پیکربندی حداقلی شامل add_library برای ساخت .so و target_link_libraries برای اتصال Android log و سایر کتابخانه‌های سیستمی است.

آیا JNI در C++ برای Android اجباری است؟

JNI (Java Native Interface) — لایه میانی بین کد Java/Kotlin برنامه Android و کتابخانه C++ است. اگر C++ از Java فراخوانی شود، JNI اجباری است. می‌توان کد C++ را کاملاً از طریق NDK نوشت، اما نقطه ورود معمولاً یک Activity Java است که توابع native را فراخوانی می‌کند.

چه زمانی C++ به جای Kotlin در توسعه موبایل توجیه دارد؟

C++ برای بازی‌ها، پردازش صدا/ویدئو در زمان واقعی، بینایی کامپیوتری، رمزنگاری، شبیه‌سازی‌های فیزیکی و انتقال کتابخانه‌ها از سکوهای دیگر توجیه دارد. برای یک برنامه UI معمولی، Kotlin کارآمدتر و ساده‌تر است.

خلاصه

  • C++ — زبان چندالگویی با مدیریت دستی حافظه، مورد استفاده در Android NDK، Unity و Unreal Engine برای کد با عملکرد بالا
  • Android NDK C++ را با زنجیره ابزار Clang از LLVM به کتابخانه‌های .so برای معماری‌های ARM کامپایل می‌کند
  • Unreal Engine کاملاً بر روی C++ با سیستم بازتاب UHT ساخته شده، Unity از C++ در هسته رندرینگ و فیزیک استفاده می‌کند
  • JNI — پل اجباری بین Java/Kotlin و C++ در Android با قرارداد نام‌گذاری Java_<بسته>_<کلاس>_<متد>
  • CMake — سیستم اصلی ساخت برای C++ در NDK، پشتیبانی از C++20 و یکپارچه‌سازی با Gradle
  • NEON SIMD تا ۴x شتاب در پردازش داده بر روی پردازنده‌های ARM از طریق دستورالعمل‌های برداری ۱۲۸ بیتی فراهم می‌کند
  • اشتباهات رایج: نشت حافظه، ABI نادرست در abiFilters، فراخوانی‌های مکرر JNI و چندنخی بدون AttachCurrentThread

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید