3

jclassC / C ++では、宣言されたメソッドを使用してネイティブ関数をJavaクラスに登録するために値が必要ですnative

このJavaクラスについて考えてみましょう。

public class Native {
  public native int f(int i);
}

ネイティブC/C ++関数を登録するにはNative.f()、C++側でこれを呼び出す必要があります。

JNIEnv* env = ...;
jclass nativeClass = ...;

JNINativeMethod nativeMethod = {
  (char*) "f",
  (char*) "(I)I",
  (void*) Java_org_example_Native_f // The native C function
};

env->RegisterNatives(nativeClass, &nativeMethod, 1);

問題のある部分はjclass、デフォルトのクラスローダーからクラスにアクセスできない場合に値を取得することです。これは、クラスNativeが、JVM内で実行されているOSGiコンテナー(Equinoxなど)内にロードされたOSGiバンドルに存在する場合には当てはまりません。

クラスにアクセスするには、Java関数を使用してClass<?>クラスのインスタンスを返します。

public class Helper {
  public static Class<?> getNativeClass() {
    // Find bundle from system bundle context.
    Bundle bundle = ... // details left out.

    return bundle.loadClass("org.example.Native");
  }
}

この関数は、OSGiコンテナーの外部のクラスにあります。JNIを使​​用してC++側からこの関数を呼び出すjobjectと、のインスタンスであるが得られますjava.lang.Class<>

// Load the `Helper` class.
jclass helperClass = env->FindClass("org.example.Helper");

// Get the method `Helper.getNativeClass()`.
jmethodId mid = env->GetStaticMethodID(helperClass,
                                       "getNativeClass",
                                       "()Ljava/lang/Class;");

// Call `Helper.getNativeClass()`.
jobject nativeClassInstance = env->CallStaticObjectMethod(helperClass, mid);

問題は、(値ではなく)「jclass」値が本当に必要なことjobjectです。Nativeそれを取得するために、クラスのオブジェクトをインスタンス化し、jclassそこから取得します。

// This is the jclass for 'java.lang.Class<>'.
jclass classClass = env->GetObjectClass(nativeClassInstance);

// Now get the method id for function 'newInstance()'
jmethodId newInstanceMid = env->GetMethodID(helperClass,
                                            "newInstance",
                                            "()Ljava/lang/Object;");

// Instantiate our 'Native' class calling 'Class<Native>.newInstance()'.
jobject nativeInstance = env->CallObjectMethod(classClass,
                                               nativeClassInstance,
                                               newInstanceMid);

// Now, I can get the desired 'jclass' of my 'Native' class.
jclass nativeClass = env->GetObjectClass(nativeInstance);

Nativeしかし、これはクラスをインスタンス化できるためにのみ機能します。

クラスjclassのオブジェクトをインスタンス化せずに目的を取得する方法はありますか?Native

4

2 に答える 2

6

ヘルパーメソッドによって返されるjobjectof型を、キャストするだけで使用できるはずです。Class<Native>jclass

jclass nativeClass = (jclass)nativeClassInstance;
于 2013-01-12T10:19:23.240 に答える
0

ネイティブコードスタブをバンドルで定義する必要がない場合は、これを行う簡単な方法があります。

JVMのクラスパスにあるクラス内にネイティブコードを配置します。org.osgi.framework.system.packages.extra=package.in.jvmバンドルを起動するときに使用します。これで、パッケージがOSGiバンドルから利用可能になり、リンクした後でネイティブ関数を呼び出すことができます。

于 2021-10-17T18:42:06.953 に答える