From the previous documentation on how to compile Wasm to native, we have seen how to compile the wasm app to a native object file and link it with the auxiliary library to the native binary, both sandbox
mode and no-sandbox
mode, to produce the final product(executable file, shared library, or static library). In this section, we will explore the difference between sandbox
and no-sandbox
modes in more details and how you may use the shared library and static library(complete sample code can be found in this directory)
The sandbox mode is the default mode when compiling the wasm app to native. As its name suggests, it preserves the Wasm sandbox mechanism, and the Wasm address space and native address space are kept separate.
# Example of compiling wasm app to native object file in sandbox mode
./wasm2native --format=object --heap-size=16384 -o main.o main.wasm
In the sandbox mode, the native binary object file will export the API defined in w2n_export.h
, you can use them in the host native binary to interact with the wasm app, such as wasm_instance_create
, wasm_get_export_apis
can be used to lookup the wasm function and then call it. You can also get exceptions, the base address and size of linear memory, host-managed heap information, etc.
And the native binary object needs to be further linked with libc-builtin.c
to provide C standard library APIs. After that, it can mainly used in two ways:
1. Link with source files like wasm_application.c
and main.c
to generate an executable file as the final product
As we can see in compile wasm applications to native binary, the wasm2native
compiler can generate an executable file by linking with auxiliary library libvmlib.a
which includes source files wasm_application.c
and main.c
.
When linking with source files like wasm_application.c
and main.c
, an executable file is generated, and the --invoke func
and --repl
command line options are supported to call a function. If these two options are not used, the default is to execute the main function of the wasm app, if it exists.
For example, for this hello world sample code, you can use it like:
# run main wasm function
./test_mem32
# the result will be 0x5:i32
./test_mem32 --invoke add 2 3
# it will show the prompt like "webassembl>", and you can run the command like "add 3 4", it will return the result "0x7:i32"
./test_mem32 --repl
webassembly> add 3 4
0x7:i32
For more details, you can refer to the this section.
2. If wasm_application.c
and main.c
are not linked, then normally a library(either static library or dynamic library) is generated as final product
When using this library, normally in the other source code that the native object file is linked with, use export APIs defined in w2n_export.h
to interact with the wasm app.
Now let's take a look at how to use the static library, for the sandbox shared library, after linking, you can use the shared library in the other source code that the native object file linked with, that other source needs to use export APIs defined in w2n_export.h
to properly handle the wasm instance, lookup the wasm function, and call it. One example is shown below, use wasm_application.c
and main.c
in the directory wasm2native-vmlib/application
.
gcc -O3 -o sandbox_with_sharedlib \
extracted_objs/main.c.o extracted_objs/wasm_application.c.o \
-L. -lsharedsandbox
# Example usage of executable(call main function of wasm app)
LD_LIBRARY_PATH=$PWD ./sandbox_with_sharedlib
# Example usage of executable(print help info)
LD_LIBRARY_PATH=$PWD ./sandbox_with_sharedlib --help
Similar to the shared library, you can use the static library in the other source code that the native object file linked with, that other source needs to use export APIs defined in w2n_export.h
to properly handle the wasm instance, lookup the wasm function, and call it.
gcc -O3 -o sandbox_with_staticlib \
extracted_objs/main.c.o extracted_objs/wasm_application.c.o \
-L. -lstaticsandbox
# Example usage of executable(call main function of wasm app)
./sandbox_with_staticlib
In the no-sandbox mode, the Wasm sandbox is discarded, and the Wasm address space and native address space are the same. This allows sharing pointers (e.g., memory pointers, function pointers) between Wasm and native.
# Example of compiling wasm app to native object file in no-sandbox mode
./wasm2native --format=object --no-sandbox-mode -o nomain_nosandbox.o nomain.wasm
PS: Normally the wasm object file shouldn't have a main function since the main function normally is provided by the host native binary.
Normally, it will link with libc64_nosandbox_wrapper.c
, either generate an executable file(it will link with the libnosandbox.a
which includes this source code) or a library(it will link with the object file of this source code), but either way, the usage is more or less the same, it's similar to the one compiled directly by gcc. You can use the native binary generated by gcc the same way as here.
For example, hello world sample code, you can use the executable file like a normal executable file.
./test_mem64_nosandbox
For the no-sandbox library, after linking, you can use the library in the other source code that the native object file is linked with, that other source can directly use the functions in the Wasm object file.
gcc -O3 -o nosandbox_with_sharedlib ../src/nosandbox_main.c -L. -lsharednosandbox
# Example usage of executable, in the nosandbox_main.c it calls the add function in the wasm object file
LD_LIBRARY_PATH=$PWD ./nosandbox_with_sharedlib
gcc -O3 -o nosandbox_with_staticlib ../src/nosandbox_main.c -L. -lstaticnosandbox
# Example usage of executable, in the nosandbox_main.c it calls the add function in the wasm object file
./nosandbox_with_staticlib