안드로이드에서 APK는 기본적으로 Zygote를 부모로하며 Dalvik을 통해 java기반으로 만들어진다.

즉 JVM을 통해 동작하는 java class단위의 프로그램이기 때문에 기본적으로 C/C++을 사용하는데 어려움이 있다.

 

하지만 C/C++의 빠른속도와, 드라이버 제어, H/W 접근 등의 장점을 사용하기 위해

java 클래스를 C/C++과 연동하여 사용할 수 있는데 이 때 둘을 연결시켜주는 요소가 바로 JNI이다.

 

1. JNI 구조

기본적으로 JNI의 구조는 java - jni - C/C++ native library로 이루어지게 된다.

 

- java

여기서 자바란 우리가 Android Studio를 통해 APK를 생성할 때 사용하는 java 파일들을 의미한다.

ex)

public class void Main() {

  add(5,3);

}

 

- JNI

JNI는 java와 C/C++을 연결해주기 위한 모듈로써 java 코드에서는 C/C++로 구현된 라이브러를 마치 Android, java 표준 라이브러리를 가져와 사용하듯 함수를 호출해서 사용할 수 있게 해준다.

 

여기서 JNI코드는 일반 코드와 달리 포맷과 규칙이 필요하다.

a) 반드시 헤더파일 jni.h를 추가해주어야 된다.

b) 함수의 포맷은 패키지명을붙여서 포맷에 맞도록 작성해야하며 매개변수로 JNIEnv*, jobject를 반드시 넣어줘야 한다.

c) int, char, string 등 자료형 사용에 있어 'j'를 붙여 jni 자료형으로 사용해야 한다.

 

ex)

#include jni.h

jint Java_com_example_test_teststringFromJNI( JNIEnv* env, jobject thiz, jint a, jint b ) {

  add_c(a,b);

}

 

- C/C++

ex)

int add (int a, int b) {

  return a+b;

}

 

결과적으로 C/C++ 코드를 만들어서 ndk를 통해 library를 만들면(Android는 Dalvik을 이용한 java이기 때문에 .so 확장자로 공유 라이브러리를 생성해야 한다) 해당 library를 dependencies에 포함하여 java에서 C/C++의 함수 및 변수를 사용할 수 있다.

 

 

2. JNI 문법

JNI는 위에서 언급한바와같이 코드를 정의하는데 규칙이 존재한다.

가장 먼저 jni.h헤더파일을 반드시 명시해야 하며 해당 명시를 통해서 java와연결이 가능하다.

그리고 함수의 포맷에 패키지명을 반드시 붙여야하고 매개변수로 Env, jobject를 반드시 추가하는데 이는 jni코드에서 java 메소드 및 변수를 호출하는데 사용되는 object와 변수이기 때문이다.

즉 실제적으로 java와의 데이터 통신을 주도하는 객체이며 java와의 통신동작은 위 매개변수를 통해 객체를 생성하고 해당 객체를 통해 java와 통신을 주고받음으로 진행된다.

 

마지막으로 jint, jstring과 같은 자료형은 java와 C/C++이 같은 char임에도 자료형이 의미하는 size가 다르고 서로 자료형 문법에 어긋나는부분이 있기 때문에 jni 자료형을 추가로만들어서 이러한 부분이 호환될 수 있기 위함이다.

 

또한 JNI 함수에는 함수 종료 시 사용했던 함수, 변수를 모두 지우는 특징이 있다.

여기서 유일하게 함수가 종료되도 메모리가 유지되며 명시적으로 제거하지 않는 조건하에 항상 유효한 값이 있는데 이는 jint 등 jni 변수를 전역 변수로 생성했을 때뿐이다.

+ Recent posts