2

如何从 Android 应用注册 JNI 回调?我的要求是,我想从 Android 应用程序进行 JNI 调用,并希望注册一个回调,以便我可以从 JNI 获取对 java 应用程序的回调。

谢谢

4

1 回答 1

0

首先,查看 Swig。它将 C++ 包装在 Java 中,并且还有一个“director”功能,可以更轻松地从 Java 调用 C++ 方法。

使用原始 JINI,您无法直接执行此操作。尽管可以调用 RegisterNatives() 来绑定本机方法,但不能更改它。如果要通过指针调用 C 函数,则需要分两步执行此操作。我掩饰了很多,因为 JNI 非常冗长和乏味。基本技巧是,将 C 函数指针包装在 java long 中。

首先声明一个java类:

public class Callback {
   public Callback(long cMethodPointer) { this.cMethod = cMethod; }
   public void doCallback() { callCMethod(cMethod); }
   public static native void callCMethod(long cMethod);
   public long cMethod;
}

在该类文件上运行 javah,您将获得一个生成的存根标头,如下所示:

JNIEXPORT void JNICALL Java_Callback_callCMethod
  (JNIEnv *, jclass, jlong);

在 DLL/so 中实现该方法:

typedef void (*FP)();
JNIEXPORT void JNICALL Java_Callback_callCMethod
  (JNIEnv *, jclass, jlong pointer) {
     ((FP)(void*)pointer)();
}

并在您的 Java main() 方法中调用该 DLL/so 上的 System.loadLibrary()。

最后,从您的 C/C++ 代码中,您需要通过 JNI 创建回调对象的实例,并将指向实际方法的指针传递给它:

void MyFunction() { ... }
void Register() {
   jclass cls = env->FindClass("Callback");
   jmethodID mid = env->GetMethodID(cls, "<init>", "(J)V");
   jvalue arg;
   arg.j = (jlong)(void*)MyFunction;
   jobject callback = env->NewObjectA(confCls, mid, &arg);
}

因此,这为您提供了一个指向您的 C 函数的全新回调对象!但是,你怎么做呢?好吧,您必须通过 JNI 将 Callback 对象传递给 Java(步骤省略),以便您的 Java 代码具有 Callback 对象,以便从中调用您的 C 方法:

public class Foo {
   public Callback callback;
   public void doSomeStuff() {
      ...
      callback.doCallback();
   }
}
于 2015-03-22T14:04:23.997 回答