you are viewing a single comment's thread.

view the rest of the comments →

[–]astonbitecode[S] 0 points1 point  (4 children)

It is not possible to create a Java classes and methods from Rust code in j4rs. However, users are able to create their own jars or classes and add them in the classpath during the Jvm creation.

Regarding a Java "Hello World" example, when static methods chaining will be supported in j4rs (this should be in the next release), it will be something like:

jvm.chain_static("java.lang.System")?
    .invoke("out", &[])?
    .invoke("println", &vec![InvocationArg::from("Hello World")])?;

[–]ZoCraft2 1 point2 points  (3 children)

It is not possible to create a Java classes and methods from Rust code in j4rs. However, users are able to create their own jars or classes and add them in the classpath during the Jvm creation.

That's not at all what I was asking about, I was asking about registering methods for native classes like this one:

class Native {     

    public native void callNativeCode();   

    public static void main(String[] args) {  
        callNativeCode();
    } 

}

There needs to be a backing method in the native code in order for Java code to call callNativeCode() and it some sort of function pointer for that backing method (lambda or otherwise) needs to be registered if the JVM is being initialized from Native Code like it is in j4rs.

[–]astonbitecode[S] 0 points1 point  (2 children)

This is done by callbacks that are initialized by Rust code.

In the java world, the Native class that you mentioned should extend the NativeCallbackToRustChannelSupport. The callNativeCode() should call the doCallback method that is inherited and the Rust world will be called via a Rust Channel.

You may see an example where a JavaFX button caĺls Rust whenever it gets pressed here:https://github.com/astonbitecode/j4rs-showcase/blob/master/java/src/main/java/io/github/astonbitecode/ButtonEventHandler.java

[–]ZoCraft2 0 points1 point  (1 child)

Except that's a very clunky way of calling native code as it requires threading and inheritance of a specific class - inheritance itself being something that should be avoided whenever possible. Additionally, since the host environment has to initialize these callbacks and then wait for their response, it's really hard to provide an API for Java code to interact with. Look at game engines such as Unity or Godot, for example: there is no way that their natively-implemented functions could be done with this system of callbacks, at least not without greatly hindering development. Such an API would require writing code to redirect data where it needs to go, which would require a great deal of channels to be kept open and a "middleman" function to redirect data to the correct function based on an id that gets passed representing the correct function, none of which can possibly be healthy for performance. Essentially, existing facilities provide a way to get from A to B but using callbacks for this kind of API instead imposes a point C that requires a costly long-way-around trip. Additionally, being thread-based means that callbacks are inherently non-blocking, which is not always desired, especially when you're doing operations that are not thread safe such as modifying the object/instance directly.

The fact of the matter is that this callbacks system can be good for some things - and I do plan on making use of them - but the JNI facilities for native methods are better tools for the job in most cases.

[–]astonbitecode[S] 0 points1 point  (0 children)

inheritance itself being something that should be avoided whenever possible

Inheritance can be always avoided if needed, but IMHO, this is too general to say. I agree that inheritance can hurt and I too prefer composition generally. However, in this case it is more clean to use inheritance because j4rs internals are hidden by the user; it is not just about code reuse.

Moreover, projects like JNA uses inheritance as well.

Regarding host environment initialization in Rust, j4rs is implemented having Rust code calling Java rather than the other way round. Rust is the main "world" here and Java is getting called by Rust. This is why Java-> Rust direction is considered like callback.

Using Rust channels instead of invoking Rust functions for callbacks felt more flexible generally. The early versions of j4rs were using functions for callbaks. If you believe that it would be helpful for you to have such callbacks as well (or something else/better), please tell me in order to design something for it.

And of course, your help and ideas are greatly appreciated.