VCF Automation Blog

from Stefan Schnell

C and C++ have been very popular programming languages for a long time and still are today. Many consolidated program approaches and libraries exists. With Emscripten is it possbile to transfer existing C / C++ projects into WebAssembly (Wasm). Wasm is a binary instruction format and it is designed as a portable compilation for different targets. This means different architectures, different operating systems, different execution environments such as browser, desktop or server - one for all. This makes Wasm a very interesting approach.

Dylibso, a group of software builders, has set itself the target of making Wasm to everyone's favorite binary format. Among other interesting products, they are developing Chicory, a JVM native Wasm runtime. It allows to run Wasm programs with zero native dependencies on any Java system. So this approach can also be used with VCF Automation. This is described in this blog post.

Use C / C++ Language via JShell


First, the necessary Java archive (Jar) files must be downloaded from the MVN repository.

Store Jar and Wasm Binaries as Action

The jar files are zip packages. They are only available as a binary format. To use them in VCF Automation, they must be encoded with base64 and can then be saved as an action. The base64 encoded content can simply be copied and pasted into the action. This also applies to the Wasm file, which was built by compiling the C code.

References


C Code

Here a tiny C program with one function, named hello. It delivers a Hello World message, depending on whether a name is passed as a parameter. If a name is passed it is used, otherwise a standard text.

#include <emscripten.h>
#include <stdlib.h>
#include <string.h>

EMSCRIPTEN_KEEPALIVE
void hello(char* name, char* result) {
  if (name == NULL) {
    char* ret = "Hello World from WebAssembly in C Language\n";
    strcpy(result, ret);
  } else {
    char* ret = "Hello ";
    strcat(ret, name);
    strcat(ret, " from WebAssembly in C Language\n");
    strcpy(result, ret);
  }
}

Compile the C Code to WebAssembly

Now we compile the code with the following command:

@emcc hello.c -o hello.c.wasm --no-entry -s EXPORTED_FUNCTIONS=_malloc,_free

After compilation we have a new file, hello.c.wasm.

Hint: This file must also be encoded as base64 and saved as an action, as described above.

Java Code in JShell

The following Java code contains seven steps. The wasm is instantiated and the functions are determined. The memory, for the parameter and the return value, is then allocated and the parameter is set. The function is executed and the return value is read. Finally the allocated memory is released.

/env --class-path /lib/vco/app-server/temp/log-0.0.10.jar:/lib/vco/app-server/temp/runtime-0.0.10.jar:/lib/vco/app-server/temp/wasi-0.0.10.jar:/lib/vco/app-server/temp/wasm-0.0.10.jar

/**
 * Example Java code in JShell to execute WebAssembly via Chicory
 *
 * @author Stefan Schnell <mail@stefan-schnell.de>
 * @license MIT
 * @version 0.1.0
 *
 * Checked with Aria Automation 8.17.0
 */

import com.dylibso.chicory.runtime.ExportFunction;
import com.dylibso.chicory.runtime.Instance;
import com.dylibso.chicory.runtime.Memory;
import com.dylibso.chicory.runtime.Module;
import com.dylibso.chicory.wasm.types.Value;
import java.io.File;

// Instantiate Wasm
File file = new File("/lib/vco/app-server/temp/hello.c.wasm");
Module module = Module.builder(file).build();
Instance instance = module.instantiate();

// Get functions from Wasm
ExportFunction hello = instance.export("hello");
ExportFunction malloc = instance.export("malloc");
ExportFunction free = instance.export("free");
Memory memory = instance.memory();

// Allocate memory for parameter and set the parameter
String name = "Stefan";
int ptrName = malloc.apply(Value.i32(name.length()))[0].asInt();
memory.writeString(ptrName, name);

// Allocate memory for return value
int ptrResult = malloc.apply(Value.i32(128))[0].asInt();

// Invoke Wasm function
hello.apply(Value.i32(ptrName), Value.i32(ptrResult));

// Get return value
String result = memory.readString(ptrResult, 128);
java.lang.System.out.println(result.trim());

// Free memory
free.apply(Value.i32(ptrResult));
free.apply(Value.i32(ptrName));

/exit

VCF Automation JavaScript Action

The action writes all the necessary files to the temporary directory. Then the JShell command is invoked with the Java code and the return value is output.

function main() {

  System.getModule("de.stschnell").writeActionAsFileInTempDirectory(
    "de.stschnell",
    "log_0_0_10_jar_base64",
    "log-0.0.10.jar",
    true,
    "application/java-archive"
  );

  System.getModule("de.stschnell").writeActionAsFileInTempDirectory(
    "de.stschnell",
    "runtime_0_0_10_jar_base64",
    "runtime-0.0.10.jar",
    true,
    "application/java-archive"
  );

  System.getModule("de.stschnell").writeActionAsFileInTempDirectory(
    "de.stschnell",
    "wasi_0_0_10_jar_base64",
    "wasi-0.0.10.jar",
    true,
    "application/java-archive"
  );

  System.getModule("de.stschnell").writeActionAsFileInTempDirectory(
    "de.stschnell",
    "wasm_0_0_10_jar_base64",
    "wasm-0.0.10.jar",
    true,
    "application/java-archive"
  );

  System.getModule("de.stschnell").writeActionAsFileInTempDirectory(
    "de.stschnell",
    "hello_c_wasm_base64",
    "hello.c.wasm",
    true,
    "application/wasm"
  );

  System.getModule("de.stschnell").writeActionAsFileInTempDirectory(
    "de.stschnell",
    "hello_jsh",
    "hello.jsh"
  );

  var jshFileName = System.getTempDirectory() + "/hello.jsh";

  var output = System.getModule("de.stschnell").executeCommand(
    ["jshell", jshFileName], 10000
  ).output;

  System.log(output);

}

// Main
main();

Here a part of the code and the log output in VCF Automation.

vcf automation action

Conclusion

With Emscripten it is very easy to convert C / C++ functions into Wasm and with Chicory it is also very easy to use Wasm inside Aria Automation with the JavaScript runtime environment. This approach offers possibilities to use and reuse C / C++ code seamlessly in Aria Automation.