오랜만에 JNI의 감동적인 노트를 만져봤습니다.
필기하는 김에 한번 썼다.
도대체 JNI가 뭐예요?
JNI(Java Native Interface) Java 플랫폼에서는 Java 기술 프로그램을 사용하여 다른 프로그래밍 언어(예: C 또는 C++ 등)로 작성된 실제 CPU에서 동작하는 코드(네이티브 코드)와 협업하는 인터페이스 사양입니다.
Wikipedia
환경 구축
대략 다음과 같은 절차.
app/build.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_hello
의 xxx
에는 가방 이름이 포함되어 있습니다.5. 설정 추가
app/build.gradle
app/build.gradleandroid {
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
Reference
이 문제에 관하여(오랜만에 JNI의 감동적인 노트를 만져봤습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/Slowhand0309/items/9cf7e7328f5c5e20b277텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)