回电话给JNI

时间:2012-11-29 13:07:37

标签: java-native-interface

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

由于

1 个答案:

答案 0 :(得分:0)

首先,看看Swig。它用Java包装C ++,并且还具有“导向器”功能,可以更容易地从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 /中实现该方法:

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

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

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

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);
}

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

public class Foo {
   public Callback callback;
   public void doSomeStuff() {
      ...
      callback.doCallback();
   }
}