Android NDK

윤찬·2025년 6월 25일

Android

목록 보기
4/37

NDK란?

네이티브 개발 키트(NDK)는 Android에서 C및 C++ 코드를 사용할 수 있게 해주는 일련의 도구 모음으로, 네이티브 액티비티를 관리하고 센서 및 터치 입력과 같은 실제 기기 구성요서에 액세스하는 데 사용할 수 있는 플랫폼 라이브러리를 제공한다.


NDK를 사용하는 이유

아래의 경우에 NDK를 사용하는 것이 적합하다

  • 기기의 성능을 최대한 활용하여 짧은 지연 시간을 구현해야 하거나 게임 또는 물리학 시물레이션과 같은 컴퓨팅 집약적 애플리케이션을 실행해야 할 때
  • 다른 개발자의 C또는 C++ 라이브러리를 재사용해야하는 경우

NDK 설치하기

공식 문서를 참조하여 작성했다. NDK 및 CMake 설치

1. SDK Manager 설정

먼저 NDK를 사용하려면 안드로이드에서 NDK와 CMake를 설치해야 한다.
프로젝트에서 Tools > SDK Manager로 이동한 후 SDK Tools 탭에서 NDK와 CMake 설치하기

이후 설치한 후 이를 사용할 모듈에 아래와 같이 적용

//...

android {
    //...
    defaultConfig {
        //...
        externalNativeBuild {
            cmake {
            	//cmake를 사용할 때 추가 설정들(추가 설정 안함) 컴파일러 추가 플래그들
                //예를 들면 아래 것들이 있음
                /**
                	cppFlags += "-std=c++17" //C++17 표준 사용
                    cppFlags += "-DDEBUG_MOD" // #ifdef DEBUG_MODE처럼 사용할 수있는 전처리기 정의
                */
                cppFlags += ""
            }
        }
    }

    //...
    //여기에 CMake를 사용하는 파일의 위치와 버전을 저장.
    //파일 위치는 추후에 만들 예정이고, Version은 SDK Manager에서 확인 가능
    externalNativeBuild {
        cmake {
            path = file("src/main/cpp/CMakeLists.txt")
            version = "3.22.1"
        }
    }
    
    //NDK version 또한 SDK Manager에서 확인 가능
    ndkVersion = "27.0.12077973"
}

2. cpp 패키지와 CmakeLists.txt와 ndkex.cpp 파일 생성

2.1 CMake는 또 뭘까?

CMake는 C/C++ 프로젝트를 빌드하기 위한 도구입니다. 다양한 플랫폼(Windows, Linux, macOS, Android 등)에서 같은 코드로 빌드가 가능하게 도와줍니다.

  • NDK에서도 CMake를 이용해 .cpp → .so 파일을 만드는 데 사용

2.2 Android NDK에서 CMake를 쓰는 이유?

Android에서는 NDK를 통해 C/C++ 코드를 빌드하여 .so(shared object, 네이티브 라이브러리) 파일을 만들 수 있다. 이 과정에서 아래와 같은 문제가 발생하는데

  • C/C++ 컴파일은 단순하지 않다.
  • 다양한 CPU 아키텍처를 지원해야 한다.
  • Java/Kotlin과 네이티브 코드를 연결해야 한다.(JNI)

이 문제를 자동화하고 관리해주는 역할이 CMake이기 때문에 이를 사용하는 것이다.

이제 위에 build.kts에서 정의한 디렉토리에 CMakeLists.txt를 만들어보자
위치는 src/main/cpp/CManeLists.txt다.
아래 사진처럼 main안에 new -> directory를 통해 cpp을 만들고 아래 2개의 파일을 만들었다.

CMakeLists.txt파일에는 아래와 같은 코드를 작성
이 코드를 작성한 이유는 공식 문서를 참고하여 작성했다.

cmake_minimum_required(VERSION 3.22.1)

project("ndkex3")

add_library(${CMAKE_PROJECT_NAME} SHARED ndkex.cpp)


target_link_libraries(${CMAKE_PROJECT_NAME}
        android
        log)

이후 ndkex.cpp파일을 아래와 같이 작성

#include <jni.h>

# 간단한 두 수를 받아서 더한 값 가져오기
extern "C"
JNIEXPORT jint JNICALL
# Java_com_example -> java.com.example 패키지
# NativeLib -> 해당 패키지에 있는 클래스이름
# addTwoNumbers -> 선언한 함수
Java_com_example_NativeLib_addTwoNumbers(
        JNIEnv* env,
        jobject /* this */,
        jint a,
        jint b) {
    return a + b;
}

코드는 cpp파일이지만 jni 문법을 사용한 코드다.

3. NativeLib 클래스에서 ndkex.cpp에서 선언한 함수 등록하기

위치는 아래와 같다 ndkex.cpp에서 함수이름처럼 java.com.example 아래에 NativeLib 클래스를 만들자.

class NativeLib {
    companion object {
        init {
        	//여기서 들어가는 ndkex3는 프로젝트 이름이다.
            System.loadLibrary("ndkex3")
        }
    }

	//external을 이용해 cpp에 있는 함수를 가져온다.(이름과 들어가야하는 파라미터가 같아야함)
    external fun addTwoNumbers(a: Int, b: Int): Int
}

4. MainActivity에서 NativeLib 사용하기

class MainActivity : ComponentActivity() {
	//NativeLib 클래스 가져오기
    private val ndkLibs = NativeLib()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            NdkEx3Theme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Greeting(
                    	//함수 사용해보기 1+2 = 3
                        name = "${ndkLibs.addTwoNumbers(1,2)}",
                        modifier = Modifier.padding(innerPadding)
                    )
                }
            }
        }
    }
}

앱을 실행하면 화면에 3이 나오는 것을 볼 수 있다.


번외 - 딸깍으로 자동 C++모듈 만들기

근데 사실 이렇게 직접 정의를 하지 않아도 아래와 같이 버튼 딸깍으로 생성이 가능하다
사용할 프로젝트 모듈의 오른쪽 클릭 후 Add C++ to Module만 누르면 자동으로 설정을 맞춰준다.(버전 또한 정해져서 맞춰줌)

이것만 누르면 위에서 행동했던 모든것들이 기본적으로 만들어진다. ㄷㄷㄷ


사실 Cpp도 일반 Cpp 코드가 아닌 JNI 문법을 사용하기 때문에 JNI에 대해 공부를 더 해야할 것 같다. 추후에 JNI 문법 예시를 공부할 기회가 오면 블로그에 정리할 예정이다.

profile
좋은 개발자가 되기까지

0개의 댓글