Skip to content
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

Add README section for host modules #518

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,97 @@ writeResultFile("hostFunction.result", hostFunctionResult);
```
-->

### Host Function Modules

Instead of writing host functions by hand, you can write a class containing annotated methods
and let the Chicory annotation processor generate the host functions for you. This is especially
useful when you have many host functions or want to pass strings from Wasm to Java.

```java
@HostModule("demo")
public final class Demo {
@WasmExport
public long add(int a, int b) {
return a + b;
}

// This function expects two arguments: ptr, len
// ptr = pointer to a string
// len = length of the string
@WasmExport
public void print(@Buffer String data) {
System.out.println(data);
}

// This function expects a pointer to a null-terminated string
@WasmExport
public void printx(@CString String data) {
System.out.println(data);
}

@WasmExport // the Wasm name is random_get
public void randomGet(Memory memory, int ptr, int len) {
byte[] data = new byte[len];
random.nextBytes(data);
memory.write(ptr, data);
}

public HostFunction[] toHostFunctions() {
return Demo_ModuleFactory.toHostFunctions(this);
}
}
```

The `@HostModule` annotation marks the class as a host module and specifies the module name for
all the host functions. The `@WasmExport` annotation marks a method as host function and optionally
specifies the name of the function. If the name is not specified, then the Java method name is
converted from camel case to snake case, as is a common convention in Wasm.

The `Demo_ModuleFactory` class in `toHostFunctions()` is generated by the annotation processor.

Host functions must be instance methods of the class. Static methods are not supported.
This is because host functions will typically interact with instance state in the host class.

To use the host module, you need to instantiate the host module and fetch the host functions:

```java
var demo = new Demo();
var imports = new HostImports(demo.toHostFunctions());
```

The following conversions are supported:

| Java Type | Wasm Type |
|-------------------|------------|
| `int` | `i32` |
| `long` | `i64` |
| `float` | `f32` |
| `double` | `f64` |
| `@Buffer String` | `i32, i32` |
| `@CString String` | `i32` |

#### Enabling the Annotation Processor

In order to use host modules, you need to configure the Java compiler to include the Chicory
`function-processor` as an annotation processor. Exactly how this is done depends on the build
system you are using. This is how to do it with Maven:

```xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>com.dylibso.chicory</groupId>
andreaTP marked this conversation as resolved.
Show resolved Hide resolved
<artifactId>function-processor</artifactId>
<version>0.0.12</version>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using a placeholder for the version number?
Alternatively, it needs to be updated by the release process by this script:
https://github.com/dylibso/chicory/blob/main/scripts/update-readme-version.sh

Copy link
Collaborator Author

@electrum electrum Sep 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the script will already update it, as it's the same format as a normal dependency?

Edit: seems we need to make the leading white space in the regex more flexible.

</path>
</annotationProcessorPaths>
</configuration>
</plugin>
```

### Store and Instantiating Multiple Modules

A [Store][spec] is an intermediate-level abstraction that collects Wasm function, global, memory, and table instances
Expand Down
5 changes: 5 additions & 0 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
<artifactId>function-annotations</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.dylibso.chicory</groupId>
<artifactId>function-processor</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.dylibso.chicory</groupId>
<artifactId>log</artifactId>
Expand Down
Loading