Skip to content

Support implementing Java interfaces with Dart classes #763

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dcharkes opened this issue Sep 26, 2022 · 1 comment · Fixed by dart-archive/jnigen#376
Closed

Support implementing Java interfaces with Dart classes #763

dcharkes opened this issue Sep 26, 2022 · 1 comment · Fixed by dart-archive/jnigen#376
Assignees
Labels
lang-java Related to Java support

Comments

@dcharkes
Copy link
Collaborator

dcharkes commented Sep 26, 2022

Implementation strategy 1: native methods

JNI features a way of declaring native methods.

package p.q.r;

class A {
    native double f(int i, String s);
    // ...
}
jdouble Java_p_q_r_A_f__ILjava_lang_String_2 (
     JNIEnv *env,        /* interface pointer */
     jobject obj,        /* "this" pointer */
     jint i,             /* argument dart-lang/jnigen#1 */
     jstring s)          /* argument dart-lang/jnigen#2 */
{
     /* Obtain a C-copy of the Java string */
     const char *str = (*env)->GetStringUTFChars(env, s, 0);

     /* process the string */
     ...

     /* Now we are done with str */
     (*env)->ReleaseStringUTFChars(env, s, str);

     return ...
}

https://docs.oracle.com/en/java/javase/17/docs/specs/jni/design.html

We should consider if it makes sense to add some kind of way to generate a Java class that delegates all of its methods to Dart.

This would generate:

  • Java class implementing a set of interfaces.
  • C file forwarding all methods to Dart callbacks. The Dart callbacks need to be done to a Dart object.
  • Dart interface with all the signatures.

The developer would then implement the Dart interface.

Implementation strategy 2: proxies

https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html

Pro:

  • Possibly no need to generate (and compile) C code.

Con:

  • Might be less performant.

Related issues

The more general version of:

@dcharkes dcharkes added the lang-java Related to Java support label Sep 26, 2022
@mahesh-hegde
Copy link
Contributor

In 1, we also have to specify which Java classes we really want to subclass. Generating native & java code for all classes will blow up the size of the app. These wrapper java classes can't be tree shaken by proguard, and C files also are bundled. This can be fine with small java - dart interlinking, but not general purpose libraries.

In 2, all primitive arguments are boxed, which is also significant usability disadvantage unless we also generate some code around this.

I think a bytecode generation strategy, while far-fetched, is optimal here.

Java:

@FunctionalInterface
class Runnable {
    void Run();
}

Dart:

class Runnable extends JniObject {
    void Run() => jni.methodCall(..)
    
    static JObject fromDartSubclassInstance(Runnable x) {
        // on first invocation, create bytecode for a class with appropriate native methods
        // and a long integer storing handle to dart object
        // this is a generated method, so can pass dart handles of all methods.
    }
}

I don't know how feasible this is. also, the methods have to be per-isolate. Dart GC may have to pin the reference to current obect etc.. etc..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lang-java Related to Java support
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

3 participants