The example below demonstrates how to compile a C function to WebAssembly and run it embedded in a Java application.
To run the demo, you need the following:
#include <stdio.h>
void floyd() {
int number = 1;
int rows = 10;
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= i; j++) {
printf("%d ", number);
++number;
}
printf(".\n");
}
}
int main() {
floyd();
return 0;
}
Note that floyd
is defined as a separate function and can be exported.
emcc --no-entry -s EXPORTED_FUNCTIONS=_floyd -o floyd.wasm floyd.c
The exported functions must be prefixed by
_
. If you reference that function in, for example, the Java code, the exported name should not contain the underscore.
It produces a standalone file floyd.wasm in the current working directory.
Add dependencies. The GraalVM SDK Polyglot API can be easily added as a Maven dependency to your Java project. The GraalWasm artifact should be on the Java module or class path too. Add the following set of dependencies to the project configuration file (pom.xml in the case of Maven).
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>polyglot</artifactId>
<version>${graalwasm.version}</version>
</dependency>
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>wasm</artifactId>
<version>${graalwasm.version}</version>
<type>pom</type>
</dependency>
Now you can embed this WebAssembly function in a Java application, for example:
import org.graalvm.polyglot.*;
import org.graalvm.polyglot.io.ByteSequence;
// Load the WebAssembly contents into a byte array
byte[] binary = Files.readAllBytes(Path.of("path", "to", "wasm", "file", "floyd.wasm"));
// Setup context
Context.Builder contextBuilder = Context.newBuilder("wasm").option("wasm.Builtins", "wasi_snapshot_preview1");
Source.Builder sourceBuilder = Source.newBuilder("wasm", ByteSequence.create(binary), "example");
Source source = sourceBuilder.build();
Context context = contextBuilder.build();
// Evaluate the WebAssembly module
context.eval(source);
// Execute the floyd function
context.getBindings("wasm").getMember("example").getMember("_initialize").executeVoid();
Value mainFunction =context.getBindings("wasm").getMember("example").getMember("floyd");
mainFunction.execute();
context.close();