네이티브 개발 키트(NDK)는 Android에서 C및 C++ 코드를 사용할 수 있게 해주는 일련의 도구 모음으로, 네이티브 액티비티를 관리하고 센서 및 터치 입력과 같은 실제 기기 구성요서에 액세스하는 데 사용할 수 있는 플랫폼 라이브러리를 제공한다.
아래의 경우에 NDK를 사용하는 것이 적합하다
공식 문서를 참조하여 작성했다. NDK 및 CMake 설치
먼저 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"
}
CMake는 C/C++ 프로젝트를 빌드하기 위한 도구입니다. 다양한 플랫폼(Windows, Linux, macOS, Android 등)에서 같은 코드로 빌드가 가능하게 도와줍니다.
Android에서는 NDK를 통해 C/C++ 코드를 빌드하여 .so(shared object, 네이티브 라이브러리) 파일을 만들 수 있다. 이 과정에서 아래와 같은 문제가 발생하는데
이 문제를 자동화하고 관리해주는 역할이 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 문법을 사용한 코드다.
위치는 아래와 같다 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
}
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이 나오는 것을 볼 수 있다.

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

이것만 누르면 위에서 행동했던 모든것들이 기본적으로 만들어진다. ㄷㄷㄷ
사실 Cpp도 일반 Cpp 코드가 아닌 JNI 문법을 사용하기 때문에 JNI에 대해 공부를 더 해야할 것 같다. 추후에 JNI 문법 예시를 공부할 기회가 오면 블로그에 정리할 예정이다.