-
[Android] Native Application(C/C++), NDK build ๋ฐ CMake ๊ตฌ์ฑAndroid 2022. 2. 14. 23:01๋ฐ์ํ
Native Application
Android NDK๋ C ๋๋ C++๋ฅผ Android ์ฑ์ ์ฝ์ ํ ์ ์๊ฒ ํด์ฃผ๋ ๋๊ตฌ ์งํฉ์ ๋๋ค. ์๋์ ๊ฐ์ ์ด์ ๋ก Android ํ๋ก์ ํธ์ C ๋ฐ C++ ์ฝ๋ ๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐ๊ฐ ํ์ํ ๊ฒฝ์ฐ๊ฐ ์์ ์ ์์ต๋๋ค.
- ํ๋ซํผ ๊ฐ ์ฑ ํธํ์ฑ
- ๊ธฐ์กด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฌ์ฉ, ์ฌ์ฌ์ฉํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(.so) ์ ๊ณต
- ๊ฒ์ ํ๋ก๊ทธ๋๋ฐ๊ณผ ๊ฐ์ ์ฑ ์ฑ๋ฅ ํฅ์
Android Studio์์๋ ๋ค์ดํฐ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ปดํ์ผ ๋๊ตฌ๋ก ํฌ๋ก์ค ํ๋ซํผ ํ๋ก์ ํธ์ ์ ํฉํ CMake์ CMake๋ณด๋ค ๋น ๋ฅด์ง๋ง Android๋ง ์ง์ํ๋ ndk-build๋ฅผ ์ง์ํฉ๋๋ค. ํ๋์ ํ๋ก์ ํธ์ CMake์ ndk-build๋ฅผ ๋ชจ๋ ์ฌ์ฉํ๋ ๊ฒ์ ํ์ฌ ์ง์๋์ง ์๋๋ค๊ณ ํฉ๋๋ค. ์ ๋ ndk-build๋ก ๊ตฌ์ฑํ๋ ๊ฒ๊ณผ CMake๋ก ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ 2๊ฐ์ง๋ฅผ ๋ชจ๋ ํด๋ณด๋ ค๊ณ ํฉ๋๋ค.
๊ธฐ๋ณธ ๊ตฌ์ฑ์์
๋ค์ดํฐ๋ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค๊ธฐ ์ ์ ๊ฐ๊ฐ์ ๊ตฌ์ฑ์์๋ค์ ๋ํด ํ์ ์ ํ๋ฉด ๋น ๋ฅด๊ฒ ํ๊ฒฝ ๊ตฌ์ฑ์ ํ ์ ์์ต๋๋ค.
- Shared Library : ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋ .so ํ์ผ์ ๋น๋ํฉ๋๋ค.
- Static Library : ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋ .a ํ์ผ์ ๋น๋ํฉ๋๋ค.
- Java Native Interface(JNI) : ์๋ฐ์ ๋ค์ดํฐ๋ธ ์ฝ๋์ ์ฐ๊ฒฐํด ์ฃผ๋ ์ธํฐํ์ด์ค์ ๋๋ค.
- Application Binary Interface(ABI) : ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ ๋ฐ์ด๋๋ฆฌ(๊ธฐ๊ณ์ด)์ ์ฐ๊ฒฐํ๋ ์ธํฐํ์ด์ค๋ก ๋ค์ํ Android ๊ธฐ๊ธฐ๋ ๊ฐ๊ธฐ ๋ค๋ฅธ CPU๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ์๋ก ๋ค๋ฅธ ๋ช ๋ น ์งํฉ์ ์ง์ํ๊ธฐ์ ABI ๋ช ์ํ์ฌ ์์คํ ๊ณผ ์ด๋ป๊ฒ ์ํธ์์ฉํ ์ง ์ ์ํฉ๋๋ค.
- Manifest
Android์ฉ ๋ค์ดํฐ๋ธ ์ฑ ๊ฐ๋ฐ์ ์ํ ์ผ๋ฐ์ ์ธ ํ๋ฆ์ ์๋์ ๊ฐ์ต๋๋ค.
- ์ฑ์ ์ค๊ณ์ ๋ง๊ฒ Java๋ก ๊ตฌํํ ๋ถ๋ถ๊ณผ ๋ค์ดํฐ๋ธ๋ก ๊ตฌํํ ๋ถ๋ถ์ ๊ฒฐ์ ํฉ๋๋ค.
- Android ํ๋ก์ ํธ๋ฅผ ๋ง๋ญ๋๋ค.
- JNI ํด๋๋ฅผ ์์ฑํ๊ณ ๋ชจ๋ ์ด๋ฆ, ์ฐ๊ฒฐ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ, ์ปดํ์ผํ ์์ค ํ์ผ ๋ฑ ๋ค์ดํฐ๋ธ ์ฝ๋ ๋น๋๋ฅผ ํ๊ธฐ ์ํ Android.mk ํ์ผ์ ๋ง๋ญ๋๋ค.
- ์ ํ๋ฆฌ์ผ์ด์ ABI, STL ๋ฑ์ ๊ตฌ์ฑํ๋ Application.mk ํ์ผ๋ ๋ง๋ค์ด JNI ํด๋ ์๋์ ์ ์ฅํฉ๋๋ค.
- ndk-build๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ดํฐ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(.so, .a)๋ฅผ ์ปดํ์ผํฉ๋๋ค.
- ์คํ ๊ฐ๋ฅํ .dex ํ์ผ์ ์์ฑํ๋ ์๋ฐ ๊ตฌ์ฑ์์๋ฅผ ๋น๋ํฉ๋๋ค.
- ์ฑ ์คํ์ ํ์ํ .so, .dex ๋ฐ ๊ธฐํ ๋ฆฌ์์ค๋ค์ ๋น๋กฏํ์ฌ ๋ชจ๋ ํญ๋ชฉ์ APK ํ์ผ์ ํจํค์งํฉ๋๋ค.
NDK build ๋ก ๊ตฌ์ฑ
ndk-build ์คํฌ๋ฆฝํธ๋ NDK์ Make ๊ธฐ๋ฐ ๋น๋ ์์คํ ์ ์ฌ์ฉํ๋ ํ๋ก์ ํธ๋ฅผ ๋น๋ํฉ๋๋ค. ndk-build๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ jni ํด๋ ์๋์ Android.mk ๋ฐ Application.mk ๊ฐ ๊ตฌ์ฑ๋์ด์ผ ํฉ๋๋ค. ์๋๋ก์ด๋ ์คํ๋์ค์์ ndk-build๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌ์ฑํ๋ ๋ฒ๊ณผ ndk-build ์ปค๋ฉ๋๋ฅผ ์ง์ ์คํํด์ C ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋น๋ํ๋ ๋ฒ์ ๋ฐฐ์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
NDK ์ค์น๋ ์๋๋ก์ด๋ ์คํ๋์ค์์ Tools > SDK Manager์์ ๋ค์ด๋ก๋ ๋ฐ์ ์ ์์ต๋๋ค. NDK๊ฐ ์ค์น๋๋ฉด ๋ด๋ถ์ ndk-build ์คํฌ๋ฆฝํธ๊ฐ ์๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ndk-build๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ jni ํด๋ ์๋์ Android.mk, Application.mk๊ฐ ์ ์๋์ด ์์ด์ผ ํฉ๋๋ค.
Application.mk
APP_ABI := all APP_PLATFORM := android-16 APP_STL := c++_static APP_ALLOW_MISSING_DEPS := true
Application.mk๋ ndk-build์ ํ๋ก์ ํธ ์ ์ฒด ์ค์ ์ ์ง์ ํ๋ฉฐ, ๊ธฐ๋ณธ์ ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ํ๋ก์ ํธ ๋๋ ํฐ๋ฆฌ์ jni/Application.mk์ ์ ์ฅํฉ๋๋ค. ํ์ผ ๋ด์ ์ ์ ๋์ด ์๋ ๋ณ์๋ค์ ๊ณต์๋ฌธ์๋ฅผ ๋ณด๋ฉด ์์ธํ๊ฒ ํ์ธํ์ค ์ ์์ต๋๋ค.
Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := jnicalculator LOCAL_SRC_FILES := calculator.cpp include $(BUILD_SHARED_LIBRARY)
๋ค์์ jni ํด๋ ์๋์ ์ ์๋์ด ์๋ Android.mk ํ์ผ์ ๋๋ค. Android.mk๋ ๋น๋ ์์คํ ์ ์์ค ํ์ผ ๋ฐ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค๋ช ํ๊ณ ์ฌ๋ฌ ์์คํ์ผ์ ํ๋์ ๋ชจ๋๋ก ๋น๋ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์ ๋ชจ๋์ด๋ผ๋ ๊ฒ์ ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(.a), ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(.so), ๋๋ ์คํํ์ผ์ ๋๋ค. ๋น๋ ์์คํ ์์๋ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ํ๋ฆฌ์ผ์ด์ ํจํค์ง์ ๋ฃ์ ๋ฟ์ ๋๋ค. ์์ ํ์ผ์์๋ jnicalculator ๋ผ๋ ๋ชจ๋์ด๋ฆ์ผ๋ก ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์์ฑํ๊ณ ์์ต๋๋ค. ๋ฐ๋ผ์ ๋น๋๋ฅผ ํ๊ฒ ๋๋ฉด libjnicalculator.so ํ์ผ์ด ์๊ฒจ๋๊ฒ ๋ฉ๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก ๊ฐ ๋ณ์๋ค์ ๋ํด์๋ ๊ณต์๋ฌธ์๋ฅผ ํ์ธํ์๋ฉด ๋ฉ๋๋ค.
ndk-build ๊ฒฐ๊ณผ ๋ค์๊ณผ ๊ฐ์ด ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋น๋๋๋ ๊ฒ์ ํ์ธํ์ค ์ ์์ต๋๋ค.
Java Code ๊ตฌํ
๋ช ๋ น์ด๋ก ์ง์ ์คํํ๋ ๊ฒ์ด ์๋ ์๋๋ก์ด๋ ์คํ๋์ค์์ ์คํ๋๋ ๊ฒ์ ํ๋ฒ ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
public class MainActivity extends AppCompatActivity { static { System.loadLibrary("jnicalculator"); } public native int getSum(int num1, int num2); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); int num1 = 10; int num2 = 20; int sum = getSum(10, 20); Toast.makeText(this, "sum : " + sum, Toast.LENGTH_LONG).show(); } }
๋ค์์ ์๋ฐ ์์ค์ฝ๋๋ก intํ ์ซ์๋ฅผ ๋ ๊ฐ๋ฅผ ๊ฐ์ง๊ณ ๋ค์ดํฐ๋ธ ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๊ฒฐ๊ณผ ๊ฐ์ ๋ฐ์์ ํ ์คํธ ๋ฉ์ธ์ง๋ก ์ถ๋ ฅํฉ๋๋ค.
static { System.loadLibrary("jnicalculator"); }
๋จผ์ System.loadLibrary("jnicalculator") ํจ์๋ฅผ ํธ์ถํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ .so ํ์ผ์ด ๋ก๋๋ฉ๋๋ค. ์ ์ชฝ์์ Android.mk์ ๋ชจ๋ ์ ์ํ ๋ jnicalculator๋ก ์ค์ ํ์๊ธฐ ๋๋ฌธ์ libjnicalculator.so๊ฐ ์์ฑ๋์๊ณ System.loadLibrary ๋ฉ์๋์๋ lib๊ณผ .so ๋ฅผ ์๋ตํ๊ณ ๋ชจ๋๋ช ๋ง ์ ๋ ฅํ๋ฉด ๋ฉ๋๋ค.
public native int getSum(int num1, int num2);
์ ๋ฉ์๋ ์ ์ธ์์ native ํค์๋๋ ๋ฉ์๋๊ฐ ๋ค์ดํฐ๋ธ ์ชฝ์ ๊ตฌํ๋์ด ์์์ JVM์๊ฒ ์๋ ค์ค๋๋ค.
C Code ๊ตฌํ
#include "calculator.h" JNIEXPORT jint JNICALL Java_com_example_ndkapplication_MainActivity_getSum( JNIEnv* env, jobject thiz, jint num1, jint num2){ return num1+num2; }
์ ์ฝ๋๋ ์๋ฐ ์ฝ๋์์ ๋ ๊ฐ์ง์ intํ ์ซ์๋ฅผ ๋ฐ์์ ๋ง์ ์ ๊ณ์ฐํ๋ ์ฝ๋์ ๋๋ค. ์๋ฐ ์์ค ์ฝ๋์์ ์ ์ธ๋ ๋ค์ดํฐ๋ธ ํจ์์ ์์ํ๋ฉฐ ๋ฐํ ์ ํ์ jint๋ก ์๋ฐ ๋ค์ดํฐ๋ธ ์ธํฐํ์ด์ค ์ฌ์์ ์ ์๋ ๋ฐ์ดํฐ ์ ํ์ ๋๋ค. jint ๋ค์๋ ํจ์ ์ด๋ฆ์ผ๋ก ํจํค์ง ๋ช + ์๋ฐ ํจ์ ์ด๋ฆ์ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ฑํฉ๋๋ค.
- ์์ Java_๋ฅผ ์ถ๊ฐํฉ๋๋ค.
- ํจํค์ง๋ช (์ต์์ ์์ค ๋๋ ํ ๋ฆฌ์ ์๋์ ์ธ ํ์ผ ๊ฒฝ๋ก), .์ _๋ก ๋์ฒดํฉ๋๋ค.
- ์กํฐ๋นํฐ ๋ช ์ ์ถ๊ฐํฉ๋๋ค.
- ๋ง์ง๋ง์๋ ๋ค์ดํฐ๋ธ ํจ์ ์ด๋ฆ์ ์ถ๊ฐํฉ๋๋ค.
์ด๋ฌํ ๊ท์น์ ํตํด์ ํจ์ ์ด๋ฆ์ด Java_com_example_ndkapplication_MainActivity_getSum์ผ๋ก ์ฌ์ฉํฉ๋๋ค. ์ด ์ด๋ฆ์ด getSum() ์ด๋ผ๋ ์๋ฐ ํจ์ ๊ฐ๋ฆฌํต๋๋ค.
C header ๊ตฌํ
#include <jni.h> /* Header for class com_example_ndkapplication_MainActivity */ #ifndef _Included_com_example_ndkapplication_MainActivity #define _Included_com_example_ndkapplication_MainActivity #ifdef __cplusplus extern "C" { #endif /* * Class: com_example_ndkapplication_MainActivity * Method: getSum * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_example_ndkapplication_MainActivity_getSum (JNIEnv *, jobject, jint, jint); #ifdef __cplusplus } #endif #endif
header ์ถ๊ฐ๋ javah Tool์ ์ ์ํ์ฌ ์ฝ๊ฒ ์ถ๊ฐํ ์ ์์ต๋๋ค. ์์ธํ ๋ด์ฉ์ ์๋ ๋ธ๋ก๊ทธ๋ฅผ ํ์ธํ๋ฉด ๋ฉ๋๋ค.
https://math-coding.tistory.com/177
Gradle ๊ตฌ์ฑ
๋ค์ดํฐ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ๋ก์ ํธ๋ฅผ Gradle ๋น๋ ์ข ์ ํญ๋ชฉ์ผ๋ก ํฌํจํ๋ ค๋ฉด Gradle์ CMake ๋๋ ndk-build ์คํฌ๋ฆฝํธ ํ์ผ์ ๊ฒฝ๋ก๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค. ์ฑ์ ๋น๋ํ๋ฉด Gradle์ CMake ๋๋ ndk-build๋ฅผ ์คํํ๊ณ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฑ์ผ๋ก ํจํค์งํฉ๋๋ค. ์๋์ผ๋ก Gradle์ ๊ตฌ์ฑํ์ฌ ๋ค์ดํฐ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฐ๊ฒฐํ๋ ค๋ฉด ๋ชจ๋ ์์ค build.gralde ํ์ผ์ externalNativeBuild ๋ฅผ ์ถ๊ฐํ์ฌ cmake ๋๋ ndkBuild ๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌ์ฑํฉ๋๋ค.
externalNativeBuild { ndkBuild { path file('src/main/jni/Android.mk') } }
์ ์์์์๋ ndkBuild๋ฅผ ์ฌ์ฉํ๊ธฐ์ Gradle์ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌ์ฑํ๋ฉด ๋น๋๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ํ ์ ์์ต๋๋ค.
๋ฐ์ํCMake ๋ก ๊ตฌ์ฑ
CMake ๋น๋ ์คํฌ๋ฆฝํธ๋ CMakeLists.txt๋ก ์ด๋ฆ์ ์ง์ ํด์ผ ํ๋ ํ ์คํธ ํ์ผ์ด๋ฉฐ ํฌ๋ก์ค ํ๋ซํผ์ ์ ํฉํ ๋น๋ ํด์ ๋๋ค. C/C++ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋น๋ํ๋ ๋ค์ํ ๋ช ๋ น์ด๋ค์ ํฌํจํ๊ณ ์์ต๋๋ค. ndk-build ๋ก ๋น๋ ์์๋ Android.mk, Application.mk ๋ฑ ๋ง์ ๊ฒ์ ์ง์ ์ถ๊ฐ๋ฅผ ํด์ผํ์ง๋ง, CMake ๋น๋๋ Project ์์ฑ ์ Native C++ Project๋ก ์ ํํ๊ฒ ๋๋ฉด ์๋์ผ๋ก ๊ธฐ๋ณธ ๊ตฌ์ฑ์ด ์ค์ ๋ฉ๋๋ค.
CMakeLists.txt ์ค์
# For more information about using CMake with Android Studio, read the # documentation: https://d.android.com/studio/projects/add-native-code.html # Sets the minimum version of CMake required to build the native library. cmake_minimum_required(VERSION 3.10.2) # Declares and names the project. project("cmakeapplication") # Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. # Gradle automatically packages shared libraries with your APK. add_library( # Sets the name of the library. cmakecalculator # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). calculator.cpp) # Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by # default, you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build. find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log) # Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in this # build script, prebuilt third-party libraries, or system libraries. target_link_libraries( # Specifies the target library. cmakecalculator # Links the target library to the log library # included in the NDK. ${log-lib})
๋ค์์ CMakeLists.txt์ ์์ฑ๋ ์คํฌ๋ฆฝํธ ๋ด์ฉ์ ๋๋ค.
- add_library : ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋ ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฅผ ์์ฑ, ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์์ฑํ๊ธฐ ์ํ ์์ค์ฝ๋ ์ ๋ ฅ
- find_library : ์ด๋ฏธ ๋น๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ช ์ง์ , log-lib(์๋๋ก์ด๋ ๋ก๊ทธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ)
- target_link_libraries : CMake์ ์ด๋ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ๋งํฌํ ์ง ๋ช ์
์ด๋ณด๋ค ๋ ์์ธํ๊ณ ์์ธํ ๋ช ๋ น์ด๋ค์ ๊ณต์๋ฌธ์ ์์ ํ์ธํ ์ ์์ต๋๋ค.
Java Code ๊ตฌํ
public class MainActivity extends AppCompatActivity { // Used to load the 'cmakeapplication' library on application startup. static { System.loadLibrary("cmakecalculator"); } private ActivityMainBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); // Example of a call to a native method TextView tv = binding.sampleText; tv.setText(String.valueOf(getSum(10,20))); } public native int getSum(int num1, int num2); }
nkd-build์ ์ฐจ์ด๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ค๋ช ์ ์๋ตํฉ๋๋ค. ๋์ผํ๊ฒ libcmakecalculator.so ํ์ผ์ด ์์ฑ๋๋ ๊ฒ์ ํ์ธํ์ค ์ ์์ต๋๋ค.
C Code ๊ตฌํ
#include <jni.h> extern "C" JNIEXPORT jint JNICALL Java_com_example_cmakeapplication_MainActivity_getSum( JNIEnv* env, jobject /* this */, jint num1, jint num2) { return num1 + num2; }
C Code๋ ndk-build ์์ ์ค์ ํ ํจ์ ์ด๋ฆ๊ณผ ๋์ผํ ๊ท์น์ด ์ ์ฉ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
Gradle ๊ตฌ์ฑ
Project ์ค์ ์ Native C++ Project๋ก ์ง์ ํ๊ฒ ๋๋ฉด ์๋์ผ๋ก ๋ชจ๋ ์์ค build.gradle์ ํฌํจ์ด ๋ฉ๋๋ค. ์๋์ ๊ฐ์ด CMakeLists.txt ํ์ผ์ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ๋ฉด ๋ค์ดํฐ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐ๊ฒฐํ ์ ์๊ฒ ๋ฉ๋๋ค.
externalNativeBuild { cmake { path file('src/main/cpp/CMakeLists.txt') version '3.10.2' } }
CMake๋ก ๊ตฌ์ฑ ์์ ABI ์ง์ ์ ndk-build์ ์ฐจ์ด๊ฐ ์์ต๋๋ค. ndk-build๋ Application.mk์์ APP_ABI ๋ณ์๋ก ์ค์ ์ ํ์๋ค๋ฉด CMake๋ก ๊ตฌ์ฑํ๊ฒ ๋๋ฉด build.gradle์ ํฌํจ์์ผ์ผ ํฉ๋๋ค.
android { ... defaultConfig { ... externalNativeBuild { cmake {...} // or ndkBuild {...} } // Similar to other properties in the defaultConfig block, // you can configure the ndk block for each product flavor // in your build configuration. ndk { // Specifies the ABI configurations of your native // libraries Gradle should build and package with your app. abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a' } } buildTypes {...} externalNativeBuild {...} }
์์ฒ๋ผ ndk.abiFilters ํ๋๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ ์ง์ ์ ํ๊ฒ ๋๋ฉด ์ํ๋ ABI๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค. ๋ชจ๋ ABI์ ๋ํด์ ์ถ๊ฐ๋ฅผ ํ๊ณ ์ถ์ผ๋ฉด all๋ก ์ง์ ์ ํด๋ ๋ฌด๋ฐฉํฉ๋๋ค.
๋ค์ดํฐ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
๋ฐํ์์ ๋ค์ดํฐ๋ธ ๋ฉ์๋๋ฅผ ์ฐพ์ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. RegisterNative ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ช ์์ ์ผ๋ก ๋ค์ดํฐ๋ธ ๋ฉ์๋๋ฅผ ๋ฑ๋กํ๊ฑฐ๋ ์์์ ํน์ ์ด๋ฆ ๊ท์น์ผ๋ก ์ง์ ํ๋ ๋ฐฉ์์ด ์์ต๋๋ค. RegisterNative์ ์ฅ์ ์ ๋ฉ์๋๊ฐ ์กด์ฌํ๋์ง ๋ฏธ๋ฆฌ ํ์ธํ๊ณ JNI_OnLoad ์ด์ธ์ ๋ฉ์๋๋ ํ์ธํ์ง ์์ผ๋ฏ๋ก ๋น ๋ฅธ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค.
- JNIEXPORT jint JNI_OnLoad(JavaVM* vm , void* reserved) ํจ์ ์ ๊ณต
- JNI_OnLoad ์์ RegisterNatives ๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ ๋ค์ดํฐ๋ธ ๋ฉ์๋ ๋ฑ๋ก
jint getSum(JNIEnv *env, jobject thiz, jint num1, jint num2) { return num1 + num2; } jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; } jclass c = env->FindClass("com/example/cmakeapplication/MainActivity"); if (c == nullptr) return JNI_ERR; static const JNINativeMethod methods[] = { {"getSum", "(II)I", (void*)getSum} }; int rc = env->RegisterNatives(c, methods, sizeof(methods) / sizeof(JNINativeMethod)); if (rc != JNI_OK) return rc; return JNI_VERSION_1_6; }
JNI_OnLoad ์์ FindClass ํธ์ถ์ ์คํํ๋ฉด ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ก๋ํ๋ ํด๋์ค๋ฅผ ์ฐพ์ ํ JNINativeMethod์ ๋ค์ดํฐ๋ธ ๋ฉ์๋๋ฅผ ์ ์ธํฉ๋๋ค. JNINativeMethod ๊ท์น์ name, signature, function name ์ ์ ๋ ฅํ๊ฒ ๋๊ณ , signature์๋ ๊ดํธ ์์๋ ๋งค๊ฐ๋ณ์ ๊ดํธ ๋ฐ์ ๋ฐํ ํ์ ์ ๋๋ค. ๋ง์ง๋ง์ผ๋ก RegisterNatives ๋ฉ์๋๋ฅผ ํตํด์ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฅผ ์ฌ์ฉํ๋ ํด๋์ค์ ์ปจํ ์คํธ์ ๋ฑ๋ก์ ํ๊ฒ ๋๋ฉด ๋ค์ดํฐ๋ธ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ฐธ๊ณ
https://developer.android.com/studio/projects/add-native-code?hl=ko
https://developer.android.com/ndk/samples/sample_hellojni?hl=ko
https://developer.android.com/training/articles/perf-jni#native-libraries
๋ฐ์ํ'Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android] Storage Access Framework(SAF) ์ด๋? (0) 2022.03.13 [Android] findViewById ์๋ฆฌ (0) 2022.03.13 [Android] ContentProvider ๊ตฌํ ๋ฐ ์ฌ์ฉ๋ฒ (0) 2022.02.05 [Android] Room ์ดํด ๋ฐ ํ์ฉ (0) 2022.01.01 [Android] SQLite, SQLiteOpenHelper, Local DB ์ดํด (0) 2021.11.30