1. 静的登録
静的登録は、JavaのメソッドとC++の関数名をJNIの命名規則に従って厳密に一致させる仕組みです。この方法は実装がシンプルですが、関数名に特定のルールが適用されます。
- Activity内でnativeメソッドを宣言
- C++側で対応する関数を実装
サンプルコード:
Java側(MainActivity):
public native String stringFromJNI();
C++側(native-lib.cpp):
extern "C" JNIEXPORT jstring JNICALL
Java_com_marxist_firstjni_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Java 调用 C++ 静态注册方法";
return env->NewStringUTF(hello.c_str());
}
2. 動的登録
動的登録は、実行時にJavaメソッドとC++関数をマッピングする仕組みです。関数名に制約がなく、柔軟性が高い方法です。
実装手順:
- Java側でnativeメソッドを宣言
- C++側で任意の名前で関数を実装
- 登録用テーブルを定義
- JVM起動時に登録処理を行う関数を実装
サンプルコード:
Java側(MainActivity):
public native String getStringFromNative();
C++側(native-lib.cpp):
jstring getStringFromNative(JNIEnv* env, jobject /* this */) {
std::string hello = "Java 调用 C++ 动态注册方法";
return env->NewStringUTF(hello.c_str());
}
登録テーブルの定義
static JNINativeMethod methods[] = {
{"getStringFromNative", "()Ljava/lang/String;", (void *)getStringFromNative}
};
JVM起動時の登録処理
jint JNI_OnLoad(JavaVM *vm,void* reserved){
JNIEnv *env = NULL;
if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
}
jclass clazz = env->FindClass("com/marxist/firstjni/MainActivity");
if (clazz == nullptr) {
return JNI_ERR;
}
if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
return JNI_ERR;
}
return JNI_VERSION_1_6;
}
3. 完全なコード例
Java側(MainActivity):
package com.marxist.firstjni;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import com.marxist.firstjni.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("firstjni");
}
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
TextView tv = binding.sampleText;
tv.setText(stringFromJNI()+"\n"+getStringFromNative());
}
public native String stringFromJNI();
public native String getStringFromNative();
}
C++側(native-lib.cpp):
#include
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_marxist_firstjni_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Java 调用 C++ 静态注册方法";
return env->NewStringUTF(hello.c_str());
}
jstring getStringFromNative(JNIEnv* env, jobject /* this */) {
std::string hello = "Java 调用 C++ 动态注册方法";
return env->NewStringUTF(hello.c_str());
}
static JNINativeMethod methods[] = {
{"getStringFromNative", "()Ljava/lang/String;", (void *)getStringFromNative}
};
jint JNI_OnLoad(JavaVM *vm,void* reserved){
JNIEnv *env = NULL;
if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
}
jclass clazz = env->FindClass("com/marxist/firstjni/MainActivity");
if (clazz == nullptr) {
return JNI_ERR;
}
if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
return JNI_ERR;
}
return JNI_VERSION_1_6;
}