오랜만에 JNI의 감동적인 노트를 만져봤습니다.

9361 단어 AndroidJNIC++
오랜만에 JNI를 만져봤는데 쉬워져서 감동
필기하는 김에 한번 썼다.

도대체 JNI가 뭐예요?


JNI(Java Native Interface) Java 플랫폼에서는 Java 기술 프로그램을 사용하여 다른 프로그래밍 언어(예: C 또는 C++ 등)로 작성된 실제 CPU에서 동작하는 코드(네이티브 코드)와 협업하는 인터페이스 사양입니다.
Wikipedia

환경 구축


대략 다음과 같은 절차.
  • jni를 위한 디렉터리 만들기
  • Kotlin/Java 측의 로컬 호출용 클래스 만들기
  • CMakeLists.txt 만들기
  • 본체 측면 설치
  • app/build.gradle 추가 설정
  • CMakeLists.txtbuild 만들기.그저gradle에 기술할 뿐입니다.
    번역해서 쓸 수 있다니...아저씨 감동
    (옛날엔 Android.mk를 했었는데.)
    1. jni를 위한 디렉터리 만들기
    기본값으로 src/main/cpp 사용된 것 같습니다.
    나는 개인적으로 어디든 이해하기 쉬우면 된다고 생각한다.
    이번에 만들었어요src/main/java/xxxxx/jni.
    2. Kotlin/Java 측의 로컬 호출 클래스
    예를 들어 로컬 문자열 hello 을 되돌리는 방법이 있는 클래스를 만들어 보십시오.
    jni/SampleNative.kt
    class SampleNative {
      external fun hello(): String
    
      companion object {
        init {
          System.loadLibrary("sample-native")
        }
      }
    }
    
    ↑ 에서 지정한 sample-native 공유 라이브러리의 이름을 지정합니다.
    3. CMakeLists.txt 만들기
    jni/CMakeLists.txt
    cmake_minimum_required(VERSION 3.4.1)
    
    add_library(
            sample-native
            SHARED
            sample-native.cpp)
    
    find_library(
            log-lib
            log)
    
    target_link_libraries(
            sample-native
            ${log-lib})
    
    4. 로컬 설치
    jni/sample-native.cpp
    #ifndef __SAMPLE_NATIVE_H_
    #define __SAMPLE_NATIVE_H_
    
    #include <jni.h>
    #include <android/log.h>
    #include <string>
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    JNIEXPORT jstring JNICALL
    Java_xxx_xxx_xxx_xxx_jni_SampleNative_hello(
            JNIEnv *env,
            jobject /* this */) {
        std::string hello = "Hello from C++";
        return env->NewStringUTF(hello.c_str());
    }
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif // __SAMPLE_NATIVE_H_
    
    Java_xxx_xxx_xxx_xxx_jni_SampleNative_helloxxx 에는 가방 이름이 포함되어 있습니다.
    5. 설정 추가app/build.gradleapp/build.gradle
    android {
      defaultConfig {
            externalNativeBuild {
                cmake {
                    cppFlags ""
                }
            }
      }
      externalNativeBuild {
          cmake { path "src/main/java/xxx/jni/CMakeLists.txt" }
      }
    }
    
    이렇게 하면 개일 수 있다
    사용할 때는 일반적인 방법처럼 사용할 수 있다.
    val sample = SampleNative()
    sample.hello() // Hello from C++
    

    Tips


    실시 중에 개인적으로 편리한 것을 골랐다.

  • 로그 출력 정보
    #define TAG               "SampleNative"
    #define LOGD(...)         __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
    #define LOGE(...)         __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
    #define LOGI(...)         __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
    
    // LOGD("numbers %d %d", num1, num2);
    
    ↑ 처럼 define 하면 편해요.

  • 객체 생성
    #if defined(DEBUG) || defined(_DEBUG)
    #define __ASSERT__(e)      assert(e)
    #else
    #define __ASSERT__(e)
    #endif // DEBUG
    
    /**
     * 引数なしコンストラクタを呼び出しクラスオブジェクトを生成<br>
     *
     * @param  env       JNIEnv
     * @param  classPath クラスパス
     * @return           jobject
     */
    jobject newObject(JNIEnv *env, const char *classPath)
    {
        jclass cls = env->FindClass(classPath);
        __ASSERT__(cls != NULL);
        // コンストラクタ取得
        jmethodID mid = env->GetMethodID(cls, "<init>", "()V");
        __ASSERT__(mid != NULL);
        jobject jobj = env->NewObject(cls, mid);
        // 後片付け
        env->DeleteLocalRef(cls);
        return jobj;
    }
    
    /**
     * java.util.ArrayListクラスのインスタンス取得
     *
     * @param  env JNIEnv
     * @return     インスタンス
     */
    jobject newArrayList(JNIEnv *env)
    {
        return newObject(env, "java/util/ArrayList");
    }
    
    JNI 사이드는 Java/Kotlin 사이드 객체로 생성되는 경우가 많기 때문에 ↑ 처럼 만드는 방법이 편리하다
  • 바드의 비결


    나 JUnit 못해!

  • Android JUnit Testing for Native Libraries
    만약 네가 JUnit이라면, 너는 호스트 컴퓨터 환경의 구조로 구축할 것이다UnsatisfiedLinkError.
    ↑ 링크처럼 구축하거나 instrumented 테스트에서
  • 참조 URL

  • JNI에서 Android에서 C++ 소스 코드를 사용하여 객체를 공유하는 자습서를 시도했습니다.
  • kotlin-jni-javah.sh
  • 좋은 웹페이지 즐겨찾기