diff --git a/sites/cheerpj/src/content/docs/11-guides/Implementing-Java-native-methods-in-JavaScript.md b/sites/cheerpj/src/content/docs/11-guides/Implementing-Java-native-methods-in-JavaScript.md deleted file mode 100644 index 9e7ff689..00000000 --- a/sites/cheerpj/src/content/docs/11-guides/Implementing-Java-native-methods-in-JavaScript.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Implementing native methods and libraries -description: Java Native Interface (JNI) with CheerpJ ---- - -With CheerpJ, it is possible to implement Java 'native' methods (that would normally be implemented in C/C++ or other AOT-compiled language) in JavaScript, similarly to what would be done in regular Java using the Java Native Interface (JNI). - -You can recognise these methods in Java code by the `native` keyword in their declaration. These functions are not implemented in Java, but are instead implemented in JavaScript. - -## Using the `natives` option of `cheerpjInit` - -`cheerpjInit` accepts a `natives` object that can be used to provide implementations of native methods. The object's keys are the names of the native methods, and the values are the implementations: - -- **Key:** string in the form `Java__`. For instance, if `com.foo.Bar` has a native method called `baz`, its object key is `Java_com_foo_Bar_baz`. -- **Value:** async function that takes a [`CJ3Library`] object as its first parameter, followed by the method's parameters. The function can return a value or a Promise that resolves to a value. - -Parameters and return values are subject to [conversion rules]. - -### Example - -Consider the following Java class: - -```java title="Example.java" -public class Example { - public static void main(String[] args) { - alert("Hello, world!"); - } - - public static native void alert(String message); -} -``` - -To provide an implementation of `alert`, pass it to the `cheerpjInit` function as a property of the `natives` object: - -```js -await cheerpjInit({ - natives: { - async Java_Example_alert(lib, str) { - window.alert(str); - }, - }, -}); -await cheerpjRunMain("Example", "/app/"); -``` - -The `lib` parameter is a [`CJ3Library`]. It can be used to access other classes and methods of the library. - -Parameters and return values of JNI calls are automatically converted between JavaScript and Java types. - -## Using `System.loadLibrary` for shared/dynamic libraries - -[`System.loadLibrary(String libname)`] is a Java method that loads a native library (`.so`, `.dll`, or `.dylib` file) and makes its methods available to Java code. The library is found by searching each path in `java.library.path` for a file called `libname.so` (or `libname.dll` or `libname.dylib` on Windows and macOS, respectively). - -CheerpJ behaves the same way, but looks for files called `libname.js`. This file should be a module that exports an object with the same structure as the `natives` object described above. - -### Example - -```java title={Example.java} -public class Example { - static { - System.loadLibrary("native"); - } - - public static void main(String[] args) { - new Example().alert("Hello, world!"); - } - - private native void alert(String message); -} -``` - -```js title={native.js} -export default { - async Java_Example_alert(lib, self, message) { - window.alert(message); - }, -}; -``` - -```js -await cheerpjInit({ javaProperties: ["java.library.path=/app/"] }); -await cheerpjRunMain("Example", "/app/"); -``` - -[`CJ3Library`]: /docs/reference/CJ3Library -[conversion rules]: /docs/reference/cheerpjRunLibrary#conversion-rules -[`System.loadLibrary(String libname)`]: https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#loadLibrary-java.lang.String- diff --git a/sites/cheerpj/src/content/docs/11-guides/implementing-native-libraries.md b/sites/cheerpj/src/content/docs/11-guides/implementing-native-libraries.md new file mode 100644 index 00000000..f4c68ed9 --- /dev/null +++ b/sites/cheerpj/src/content/docs/11-guides/implementing-native-libraries.md @@ -0,0 +1,149 @@ +--- +title: Implementing Native Libraries +description: Java Native Interface (JNI) with CheerpJ +--- + +In this guide, we’ll explore how to use **native libraries** in CheerpJ to implement Java native methods in JavaScript. + +Native libraries in Java are typically loaded with the `System.loadLibrary` method allowing a Java program to call functions implemented in another language. This function is part of the **Java Native Interface (JNI)**, the same interface used to work with Java native methods, which we covered in the [`Implementing Native Methods guide`]. + +Unlike [`native methods`], native libraries are not restricted to a single Java class. They can be accessed by multiple classes and even be shared across an entire application. + +## Using `System.loadLibrary` for shared libraries + +[`System.loadLibrary(String libname)`] is a Java method that loads a shared library into the application, making the native methods within the library accessible to Java code. The Java runtime searches each path in `java.library.path` for the library file with the correct format for the operating system (`.so`, `.dll`, or `.dylib` on Linux, Windows, and macOS, respectively). + +CheerpJ adapts this concept to load JavaScript modules, using the same `System.loadLibrary` call to load `.js` files. These files are JavaScript modules that define implementations for the native methods associated with the library. + +## Steps to implement native libraries in CheerpJ + +In general, we can implement native libraries in CheerpJ by following these steps: + +1. Create a Java class that loads the JavaScript library and declares the native methods. +2. Create a JavaScript module that implements the native methods. +3. Load the native library in the Java class with CheerpJ. + +### Loading native nibraries and declaring native methods in Java + +To declare a native method in Java, use the `native` keyword in the method declaration. The method is defined in the Java class but is not implemented in Java. Instead, the implementation will be provided in the native library JavaScript module which is loaded with `System.loadLibrary`. + +```java +public class ClassName { + // Load the library file + static { + System.loadLibrary(""); + } + + // Native method declaration + private native void methodName(param1, param2, ...); +} +``` + +### Creating a JavaScript module + +A JavaScript module is a file that contains code which can be exported and imported by other files for better organization and reuse. You create modules using the `export` keyword to expose classes, methods, or other resources, and you can use `export default` to make a primary, easy-to-import item from the module. For more information on JavaScript modules, check out the official [`documentation`]. + +```js title="module.js" +export default { + // JavaScript code +}; +``` + +JavaScript functions that implement native methods should follow a specific naming convention - `Java__`. For instance, if `com.foo.Bar` has a native method called `baz`, the function will be called `Java_com_foo_Bar_baz` + +The JavaScript function should accept the following parameters: + +- A [`CJ3Library`] object `lib` as the first parameter, which provides access to other classes and methods within the library. +- `self` as the second parameter, the instance of the Java class calling the native method. This parameter can be omitted for static native methods. +- The native method’s parameters as subsequent parameters. + +The function can return a value or a Promise that resolves to a value. The function syntax is as follows: + +```js +async function Java__(lib, self, param1, param2, ...) { + // Implementation +} +``` + +> [!info] Handling Static Native Methods +> If the native method is static, the `self` parameter can be omitted. + +### Initializing CheerpJ with the `javaProperties` option + +To use a native library in CheerpJ, you need to set the `java.library.path` property to the directory containing the JavaScript module file that implements the native methods. This is done by passing the `javaProperties` option to the `cheerpjInit` function: + +```js +await cheerpjInit({ javaProperties: ["java.library.path=/app/"] }); +``` + +`/app/` is a [`virtual directory`] in CheerpJ that corresponds to the root directory of the application. + +## Example walkthrough + +In the following example, we’ll see how to create a native library in JavaScript, load it into Java with `System.loadLibrary`, and call a native method through this library from a Java class. + +1. Let's start with a Java class that loads a native library and declares a native method, `alert`, that displays an alert message in the browser. + +```java title="Example.java" +public class Example { + // Load the native.js library file + static { + System.loadLibrary("native"); + } + + public static void main(String[] args) { + new Example().alert("Hello, world!"); + } + + // Native method declaration + private native void alert(String message); +} +``` + +2. Next, we create a JavaScript module, `native.js`, that implements the `alert` method to display an alert dialog in the browser. + +```js title="native.js" +export default { + async Java_Example_alert(lib, message) { + window.alert(message); + }, +}; +``` + +3. Finally, we initialize CheerpJ with the [`javaProperties`] option to set the `java.library.path` to the directory containing the `native.js` file. Then, we run the Java `Example` class. + +```html title="index.html" {9,10} + + + + Native Method Example + + + + + + +``` + +In this example, we set the `java.library.path` to `/app/`, which is the directory where the JavaScript file implementing the native methods is located. The folder structure should look like this: + +``` +root/ + ├── Example.class + ├── native.js + ├── index.html +``` + +When the Java `Example` class is run, the `alert` method is called, which triggers the `Java_Example_alert` function in `native.js`, displaying an alert dialog with the message "Hello, world!". + +[`CJ3Library`]: /docs/reference/CJ3Library +[`conversion rules`]: /docs/reference/cheerpjRunLibrary#conversion-rules +[`System.loadLibrary(String libname)`]: https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#loadLibrary-java.lang.String- +[`native methods`]: /docs/11-guides/implementing-native-methods +[`Implementing Native Methods guide`]: /docs/11-guides/implementing-native-methods +[`virtual directory`]: /docs/guides/File-System-support +[`javaProperties`]: /docs/reference/cheerpjInit#javaproperties +[`documentation`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules