Синтаксис, который вы показываете, сводится к созданию анонимных внутренних классов во время компиляции и вставке вызовов для создания объектов этих классов (с правильными переменными в области видимости) вместо выражения new View.OnClickListener() { ... }
.
Iсм. следующие две опции:
Для каждого отдельного интерфейса вы создаете небольшой класс Java, который реализует интерфейс, с реализацией native
метода (ов) интерфейса. Это наиболее прямой подход, но он требует, чтобы вы сохранили десятки или сотни реализаций интерфейса.
Вы используете java.lang.reflect.Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
для динамического создания объектов, которые реализуют необходимые интерфейсы. Это перенаправит каждый вызов метода в вашу реализацию InvocationHandler
, которая должна быть классом Java с реализацией native Object invoke(Object proxy, Method method, Object[] args)
.
Чтобы сделать все это многоразовым, вы можете реализовать этот InvocationHandler
для переносаобъект std::function
, поэтому последний вызов, например, menuTitle.setOnClickListener
может выглядеть следующим образом:
env->CallVoidMethod(menuTitle, menuTitle_setOnClickListener,
createProxyInstance(env, cls_View_OnClickListener, [](JNIEnv *env, jobject proxy, jobject method, jobjectArray args) {
...
});
Для последнего решения определите следующий класс Java:
class MyInvocationHandler implements InvocationHandler {
private long cfunc;
MyInvocationHandler(long cfunc) { this.cfunc = cfunc; }
public native static Object invoke(Object proxy, Method method, Object[] args);
}
который вы реализуете на стороне C ++ как:
typedef jobject (*CFunc)(JNIEnv *env, jobject obj, jobject proxy, jobject method, jobjectArray args)
extern "C" jobject Java_MyInvocationHandler_invoke(JNIEnv *env, jobject obj, jobject proxy, jobject method, jobjectArray args) {
jclass cls_myIH = env->GetObjectClass(obj);
jfieldID fld_myIH_cfunc = env->GetFieldID(cls_myIH, "cfunc", "J");
CFunc cfunc = (CFunc)env->GetLongField(obj, fld_myIH_cfunc);
cfunc(env, proxy, method, args);
return nullptr;
}
Наконец, мы можем реализовать createProxyInstance
следующим образом:
jobject createProxyInstance(JNIEnv *env, jclass cls, CFunc cfunc) {
jclass cls_IH = env->GetClass("MyInvocationHandler");
jmethodID cst_IH = env->GetMethodID(cls_ID, "<init>", "(J)V");
jobject myIH = env->NewObject(cls_ID, cst_IH, (jlong)cfunc);
// now call Proxy.createProxyInstance with this object as InvocationHandler
}