The basic working flow for WASM application calling into the native API is shown in the following diagram:
WAMR provides the macro EXPORT_WASM_API
to enable users to export a native API to a WASM application. WAMR has implemented a base API for the timer and messaging by using EXPORT_WASM_API
. This can be a point of reference for extending your own library.
static NativeSymbol extended_native_symbol_defs[] = {
EXPORT_WASM_API(wasm_register_resource),
EXPORT_WASM_API(wasm_response_send),
EXPORT_WASM_API(wasm_post_request),
EXPORT_WASM_API(wasm_sub_event),
EXPORT_WASM_API(wasm_create_timer),
EXPORT_WASM_API(wasm_timer_set_interval),
EXPORT_WASM_API(wasm_timer_cancel),
EXPORT_WASM_API(wasm_timer_restart)
};
Security attention: A WebAssembly application should only have access to its own memory space. As a result, the integrator should carefully design the native function to ensure that the memory accesses are safe. The native API to be exported to the WASM application must:
- Only use 32 bits number for parameters
- Should not pass data to the structure pointer (do data serialization instead)
- Should do the pointer address conversion in the native API
- Should not pass function pointer as callback
Below is a sample of a library extension. All code invoked across WASM and native world must be serialized and de-serialized, and the native world must do a boundary check for every incoming address from the WASM world.
WAMR implemented a framework for developers to export API's. Below is the procedure to expose the platform API's in three steps:
Step 1. Create a header file
Declare the API's for your WASM application source project to include.
Step 2. Create a source file
Export the platform API's, for example in products/linux/ext_lib_export.c
#include "lib_export.h"
static NativeSymbol extended_native_symbol_defs[] =
{
};
#include "ext_lib_export.h"
Step 3. Register new API's
Use the macro EXPORT_WASM_API
and EXPORT_WASM_API2
to add exported API's into the array of extended_native_symbol_defs
.
The pre-defined MACRO EXPORT_WASM_API
should be used to declare a function export:
#define EXPORT_WASM_API(symbol) {#symbol, symbol}
Below code example shows how to extend the library to support customized()
:
//lib_export_impl.c
void customized()
{
// your code
}
// lib_export_dec.h
#ifndef _LIB_EXPORT_DEC_H_
#define _LIB_EXPORT_DEC_H_
#ifdef __cplusplus
extern "C" {
#endif
void customized();
#ifdef __cplusplus
}
#endif
#endif
// ext_lib_export.c
#include "lib_export.h"
#include "lib_export_dec.h"
static NativeSymbol extended_native_symbol_defs[] =
{
EXPORT_WASM_API(customized)
};
#include "ext_lib_export.h"
In the application source project, it will include the WAMR built-in API's header file and platform extension header files. Assuming the board vendor extends the library which added an API called customized(), the WASM application would be like this:
#include <stdio.h>
#include "lib_export_dec.h" // provided by the platform vendor
int main(int argc, char **argv)
{
int I;
char *buf = “abcd”;
customized(); // customized API provided by the platform vendor
return i;
}