@@ -36,30 +36,30 @@ let jvm = JvmBuilder::new().build()?;
36
36
37
37
// Create a java.lang.String instance
38
38
let string_instance = jvm . create_instance (
39
- " java.lang.String" , // The Java class to create an instance for
40
- & Vec :: new (), // The `InvocationArg`s to use for the constructor call - empty for this example
39
+ " java.lang.String" , // The Java class to create an instance for
40
+ InvocationArg :: empty (), // An array of `InvocationArg`s to use for the constructor call - empty for this example
41
41
)? ;
42
42
43
43
// The instances returned from invocations and instantiations can be viewed as pointers to Java Objects.
44
44
// They can be used for further Java calls.
45
45
// For example, the following invokes the `isEmpty` method of the created java.lang.String instance
46
46
let boolean_instance = jvm . invoke (
47
- & string_instance , // The String instance created above
48
- " isEmpty" , // The method of the String instance to invoke
49
- & Vec :: new (), // The `InvocationArg`s to use for the invocation - empty for this example
47
+ & string_instance , // The String instance created above
48
+ " isEmpty" , // The method of the String instance to invoke
49
+ InvocationArg :: empty (), // The `InvocationArg`s to use for the invocation - empty for this example
50
50
)? ;
51
51
52
- // If we need to transform an `Instance` to Rust value, the `to_rust` should be called
52
+ // If we need to transform an `Instance` to some Rust value, the `to_rust` should be called
53
53
let rust_boolean : bool = jvm . to_rust (boolean_instance )? ;
54
54
println! (" The isEmpty() method of the java.lang.String instance returned {}" , rust_boolean );
55
55
// The above prints:
56
56
// The isEmpty() method of the java.lang.String instance returned true
57
57
58
58
// Static invocation
59
59
let _static_invocation_result = jvm . invoke_static (
60
- " java.lang.System" , // The Java class to invoke
61
- " currentTimeMillis" , // The static method of the Java class to invoke
62
- & Vec :: new (), // The `InvocationArg`s to use for the invocation - empty for this example
60
+ " java.lang.System" , // The Java class to invoke
61
+ " currentTimeMillis" , // The static method of the Java class to invoke
62
+ InvocationArg :: empty (), // The `InvocationArg`s to use for the invocation - empty for this example
63
63
)? ;
64
64
65
65
// Access a field of a class
@@ -127,12 +127,20 @@ let my_vec: Vec<String> = vec![
127
127
let i10 = InvocationArg :: try_from (my_vec . as_slice ())? ;
128
128
```
129
129
130
+ The ` j4rs ` apis accept ` InvocationArg ` s either as references, or values:
131
+
132
+ ``` rust
133
+ let inv_args = InvocationArg :: try_from (" arg from Rust" )? ;
134
+ let _ = jvm . create_instance (" java.lang.String" , & [& inv_args ])? ; // Pass a reference
135
+ let _ = jvm . create_instance (" java.lang.String" , & [inv_args ])? ; // Move
136
+ ```
137
+
130
138
The ` Instance ` s returned by j4rs can be transformed to ` InvocationArg ` s and be further used for invoking methods as well:
131
139
132
140
``` rust
133
141
let one_more_string_instance = jvm . create_instance (
134
- " java.lang.String" , // The Java class to create an instance for
135
- & Vec :: new (), // The `InvocationArg`s to use for the constructor call - empty for this example
142
+ " java.lang.String" , // The Java class to create an instance for
143
+ InvocationArg :: empty (), // The `InvocationArg`s to use for the constructor call - empty for this example
136
144
)? ;
137
145
138
146
let i11 = InvocationArg :: try_from (one_more_string_instance )? ;
@@ -143,7 +151,7 @@ To create an `InvocationArg` that represents a `null` Java value, use the `From`
143
151
``` rust
144
152
let null_string = InvocationArg :: from (Null :: String ); // A null String
145
153
let null_integer = InvocationArg :: from (Null :: Integer ); // A null Integer
146
- let null_obj = InvocationArg :: from (Null :: Of (" java.util.List" )); // A null object of any other class. E.g. List
154
+ let null_obj = InvocationArg :: from (Null :: Of (" java.util.List" )); // A null object of any other class. E.g. List
147
155
```
148
156
149
157
### Passing custom arguments from Rust to Java
@@ -237,7 +245,7 @@ We can invoke it like following:
237
245
238
246
``` rust
239
247
let s_test = " j4rs_rust" ;
240
- let my_test = jvm . create_instance (" org.astonbitecode.j4rs.tests.MyTest" , & [] )? ;
248
+ let my_test = jvm . create_instance (" org.astonbitecode.j4rs.tests.MyTest" , InvocationArg :: empty () )? ;
241
249
let instance = jvm . invoke_async (& my_test , " getStringWithFuture" , & [InvocationArg :: try_from (s_test )? ]). await ? ;
242
250
let string : String = jvm . to_rust (instance )? ;
243
251
assert_eq! (s_test , string );
@@ -270,17 +278,17 @@ let s1 = InvocationArg::try_from("string1")?;
270
278
let s2 = InvocationArg :: try_from (" string2" )? ;
271
279
let s3 = InvocationArg :: try_from (" string3" )? ;
272
280
273
- let arr_instance = jvm . create_java_array (" java.lang.String" , & vec! [s1 , s2 , s3 ])? ;
281
+ let arr_instance = jvm . create_java_array (" java.lang.String" , & [s1 , s2 , s3 ])? ;
274
282
// Invoke the Arrays.asList(...) and retrieve a java.util.List<String>
275
283
let list_instance = jvm . invoke_static (" java.util.Arrays" , " asList" , & [InvocationArg :: from (arr_instance )])? ;
276
284
```
277
285
278
286
### Java Generics
279
287
280
288
``` rust
281
- // Assuming that the following map_instance is a Map<String, Integer>
289
+ // Assuming the following map_instance is a Map<String, Integer>
282
290
// we may invoke its put method
283
- jvm . invoke (& map_instance , " put" , & vec! [InvocationArg :: try_from (" one" )? , InvocationArg :: try_from (1 )? ])? ;
291
+ jvm . invoke (& map_instance , " put" , & [InvocationArg :: try_from (" one" )? , InvocationArg :: try_from (1 )? ])? ;
284
292
```
285
293
286
294
### Java primitives
@@ -320,15 +328,15 @@ let jvm = JvmBuilder::new().build()?;
320
328
321
329
// Create an instance
322
330
let string_instance = jvm . create_instance (
323
- " java.lang.String" ,
324
- & vec! [InvocationArg :: try_from (" a string " )? ],
331
+ " java.lang.String" ,
332
+ & [InvocationArg :: try_from (" a string " )? ],
325
333
)? ;
326
334
327
335
// Perform chained operations on the instance
328
336
let string_size : isize = jvm . chain (string_instance )
329
- . invoke (" trim" , & [] )?
330
- . invoke (" length" , & [] )?
331
- . to_rust ()? ;
337
+ . invoke (" trim" , InvocationArg :: empty () )?
338
+ . invoke (" length" , InvocationArg :: empty () )?
339
+ . to_rust ()? ;
332
340
333
341
// Assert that the string was trimmed
334
342
assert! (string_size == 8 );
@@ -349,14 +357,14 @@ In order to initialize a channel that will provide Java callback values, the `Jv
349
357
// (the class just needs to extend the
350
358
// `org.astonbitecode.j4rs.api.invocation.NativeCallbackToRustChannelSupport`)
351
359
let i = jvm . create_instance (
352
- " org.astonbitecode.j4rs.tests.MyTest" ,
353
- & Vec :: new ())? ;
360
+ " org.astonbitecode.j4rs.tests.MyTest" ,
361
+ InvocationArg :: empty ())? ;
354
362
355
363
// Invoke the method
356
364
let instance_receiver_res = jvm . invoke_to_channel (
357
- & i , // The instance to invoke asynchronously
358
- " performCallback" , // The method to invoke asynchronoysly
359
- & Vec :: new () // The `InvocationArg`s to use for the invocation - empty for this example
365
+ & i , // The instance to invoke asynchronously
366
+ " performCallback" , // The method to invoke asynchronoysly
367
+ InvocationArg :: empty () // The `InvocationArg`s to use for the invocation - empty for this example
360
368
);
361
369
362
370
// Wait for the response to come
@@ -415,7 +423,7 @@ jvm.deploy_artifact(&MavenArtifact::from("io.my:library:1.2.3"))?;
415
423
416
424
Maven artifacts are added automatically to the classpath and do not need to be explicitly added.
417
425
418
- A good practice is that the deployment of maven artifacts is done by build scripts, during the crate's compilation. This ensures that the classpath is properly populated during the actual Rust code execution.
426
+ A good practice is that the deployment of maven artifacts is done by build scripts, during the crate's compilation. This ensures the classpath is properly populated during the actual Rust code execution.
419
427
420
428
_ Note: the deployment does not take care the transitive dependencies yet._
421
429
@@ -426,8 +434,8 @@ If we have one jar that needs to be accessed using `j4rs`, we need to add it in
426
434
``` rust
427
435
let entry = ClasspathEntry :: new (" /home/myuser/dev/myjar-1.0.0.jar" );
428
436
let jvm : Jvm = JvmBuilder :: new ()
429
- . classpath_entry (entry )
430
- . build ()? ;
437
+ . classpath_entry (entry )
438
+ . build ()? ;
431
439
```
432
440
433
441
## j4rs Java library
@@ -438,7 +446,7 @@ The jar for `j4rs` is available in the Maven Central. It may be used by adding t
438
446
<dependency >
439
447
<groupId >io.github.astonbitecode</groupId >
440
448
<artifactId >j4rs</artifactId >
441
- <version >0.15.3 </version >
449
+ <version >0.18.0 </version >
442
450
<scope >provided</scope >
443
451
</dependency >
444
452
```
@@ -478,7 +486,8 @@ pub extern fn jni_onload(env: *mut JavaVM, _reserved: jobject) -> jint {
478
486
Create an ` Activity ` and define your native methods normally, as described [ here] ( #java-to-rust-support ) .
479
487
480
488
Note:
481
- If you encounter any issues when using j4rs in Android, this may be caused by Java 8 compatibility problems. This is why there is a ` Java 7 ` version of ` j4rs ` :
489
+ If you encounter any issues when using j4rs in older Android versions, this may be caused by Java 8 compatibility problems.
490
+ This is why there is a ` Java 7 ` version of ` j4rs ` :
482
491
483
492
``` xml
484
493
<dependency >
@@ -488,6 +497,8 @@ If you encounter any issues when using j4rs in Android, this may be caused by Ja
488
497
</dependency >
489
498
```
490
499
500
+ Update: Java 7 is no more supported. ` j4rs ` 0.13.1 is the last version.
501
+
491
502
## JavaFX support
492
503
(v0.13.0 onwards)
493
504
@@ -529,31 +540,31 @@ let jvm = JvmBuilder::new().with_javafx_support().build()?;
529
540
let stage = jvm . start_javafx_app ()? . rx (). recv ()? ;
530
541
531
542
// Create a StackPane. Java code: StackPane root = new StackPane();
532
- let root = jvm . create_instance (" javafx.scene.layout.StackPane" , & [] )? ;
543
+ let root = jvm . create_instance (" javafx.scene.layout.StackPane" , InvocationArg :: empty () )? ;
533
544
534
545
// Create the button. Java code: Button btn = new Button();
535
- let btn = jvm . create_instance (" javafx.scene.control.Button" , & [] )? ;
546
+ let btn = jvm . create_instance (" javafx.scene.control.Button" , InvocationArg :: empty () )? ;
536
547
// Get the action channel for this button
537
548
let btn_action_channel = jvm . get_javafx_event_receiver (& btn , FxEventType :: ActionEvent_Action )? ;
538
549
// Set the text of the button. Java code: btn.setText("Say Hello World to Rust");
539
550
jvm . invoke (& btn , " setText" , & [" A button that sends events to Rust" . try_into ()? ])? ;
540
551
// Add the button to the GUI. Java code: root.getChildren().add(btn);
541
552
jvm . chain (& root )?
542
- . invoke (" getChildren" , & [] )?
543
- . invoke (" add" , & [btn . try_into ()? ])?
544
- . collect ();
553
+ . invoke (" getChildren" , InvocationArg :: empty () )?
554
+ . invoke (" add" , & [btn . try_into ()? ])?
555
+ . collect ();
545
556
546
557
// Create a new Scene. Java code: Scene scene = new Scene(root, 300, 250);
547
558
let scene = jvm . create_instance (" javafx.scene.Scene" , & [
548
- root . try_into ()? ,
549
- InvocationArg :: try_from (300_f64 )? . into_primitive ()? ,
550
- InvocationArg :: try_from (250_f64 )? . into_primitive ()? ])? ;
559
+ root . try_into ()? ,
560
+ InvocationArg :: try_from (300_f64 )? . into_primitive ()? ,
561
+ InvocationArg :: try_from (250_f64 )? . into_primitive ()? ])? ;
551
562
// Set the title for the scene. Java code: stage.setTitle("Hello Rust world!");
552
563
jvm . invoke (& stage , " setTitle" , & [" Hello Rust world!" . try_into ()? ])? ;
553
564
// Set the scene in the stage. Java code: stage.setScene(scene);
554
565
jvm . invoke (& stage , " setScene" , & [scene . try_into ()? ])? ;
555
566
// Show the stage. Java code: stage.show();
556
- jvm . invoke (& stage , " show" , & [] )? ;
567
+ jvm . invoke (& stage , " show" , InvocationArg :: empty () )? ;
557
568
558
569
```
559
570
@@ -607,7 +618,7 @@ let stage = jvm.start_javafx_app()?.rx().recv()?;
607
618
// Set the title for the scene. Java code: stage.setTitle("Hello Rust world!");
608
619
jvm . invoke (& stage , " setTitle" , & [" Hello JavaFX from Rust!" . try_into ()? ])? ;
609
620
// Show the stage. Java code: stage.show();
610
- jvm . invoke (& stage , " show" , & [] )? ;
621
+ jvm . invoke (& stage , " show" , InvocationArg :: empty () )? ;
611
622
612
623
// Load a fxml. This returns an `FxController` which can be used in order to find Nodes by their id,
613
624
// add Event Listeners and more.
@@ -662,8 +673,8 @@ Someone may specify a different [base_path](https://docs.rs/j4rs/0.13.0/j4rs/str
662
673
663
674
``` rust
664
675
let jvm_res = j4rs :: JvmBuilder :: new ()
665
- . with_base_path (" /opt/myapp" )
666
- . build ();
676
+ . with_base_path (" /opt/myapp" )
677
+ . build ();
667
678
```
668
679
669
680
The ` base_path ` defines the location of two directories that are needed for j4rs to work;
@@ -701,8 +712,8 @@ as long as the Jvm creation is done using the `with_base_path` method:
701
712
702
713
``` rust
703
714
let jvm_res = j4rs :: JvmBuilder :: new ()
704
- . with_base_path (" /opt/myapp" )
705
- . build ();
715
+ . with_base_path (" /opt/myapp" )
716
+ . build ();
706
717
```
707
718
708
719
## FAQ
0 commit comments