Skip to content
Snippets Groups Projects
main.c 4.25 KiB
Newer Older
  #include <stdlib.h>
  #include <stdio.h>
  #include <stdint.h>
  #include "wasm_export.h"


void my_printf(wasm_exec_env_t exec_env, char *text)
{
    printf(text);
}

void my_nprintf(wasm_exec_env_t exec_env, char *text, size_t len)
{
    printf("message: '%.*s'\n", len, text);
}

void hello_world(wasm_exec_env_t exec_env) 
{
    printf("simple hello world is here \n");
}

char *read_wasm_binary_to_buffer(char *path, uint32_t *size)
{
    FILE *fd = fopen(path, "rb");
    if(!fd)
    {
        perror("fopen failed!\n");
        return NULL;
    }

    if (fseek(fd, 0, SEEK_END) != 0)
    {
        perror("fseek failed\n");
        return NULL;
    } 
    long fsize = ftell(fd);
    if(fseek(fd, 0, SEEK_SET) != 0)  // rewind(fd); can be used here too
    {
        perror("fseek failed\n");
        return NULL;
    } 

    char *buffer = malloc(fsize + 1);
    if (!buffer)
    {
        perror("malloc for file buffer failed!\n");
        return NULL;
    }
    
    size_t read_bytes = fread(buffer, 1, fsize, fd); 
    if(read_bytes != fsize)
    {
        fprintf(stderr, "file read didnt read the whole file size and returned only %zu instead of %zu \n", read_bytes, fsize);
        exit(EXIT_FAILURE);
    }
    fclose(fd);
    *size = fsize + 1;
    buffer[fsize] = 0;
    return buffer;
}

int main(int argc, char *argv[]) 
{    
    static NativeSymbol native_symbols[] = 
    {
        {
            "my_printf", 		// the name of WASM function name
            my_printf,          // the native function pointer
            "($)"		        // the function prototype signature
        },
        {
            "my_nprintf", 		// the name of WASM function name
            my_nprintf, 		// the native function pointer
            "(*~)"			    // the function prototype signature
        },
        {
            "hello_world", 		// the name of WASM function name
            hello_world, 		// the native function pointer
            "()"			    // the function prototype signature
        }    
    };

    char *buffer, error_buf[128];
    wasm_module_t module;
    wasm_module_inst_t module_inst;
    wasm_function_inst_t func;
    wasm_exec_env_t exec_env;
    uint32_t size, stack_size = 8092, heap_size = 8092;

    /* initialize the wasm runtime by default configurations */
    if(!wasm_runtime_init())
    {
        fprintf(stderr,"wasm runtime initialisation failed\n");
        exit(EXIT_FAILURE);
    }

    /* read WASM file into a memory buffer */
    buffer = read_wasm_binary_to_buffer(argv[1], &size);
    if(buffer == NULL)
    {
        fprintf(stderr, "the returned buffer for reading the wasm module is null\n");
        exit(EXIT_FAILURE);
    }
    /* add line below if we want to export native functions to WASM app */
    int n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol);
    if (!wasm_runtime_register_natives("env", native_symbols, n_native_symbols))
    {   
        free(buffer);
        exit(EXIT_FAILURE);
    }

    /* parse the WASM file from buffer and create a WASM module */
    module = wasm_runtime_load(buffer, size, error_buf, sizeof(error_buf));

    /* create an instance of the WASM module (WASM linear memory is ready) */
    module_inst = wasm_runtime_instantiate(module, stack_size, heap_size,
                                            error_buf, sizeof(error_buf));

    if(module_inst == NULL) 
    {
        fprintf(stderr, "module instantiation failed!\n");
        exit(EXIT_FAILURE);
    }
      /* lookup a WASM function by its name
     The function signature can NULL here */
    func = wasm_runtime_lookup_function(module_inst, "main", NULL);
    if (func == NULL) {
        printf("main function not found\n");
        return -1;
    }

    /* creat an execution environment to execute the WASM functions */
    exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
    if (exec_env == NULL) {
        printf("execution environmnet creation failed\n");
        return -1;
    }
    uint32_t args[1] = {0};
    if (wasm_runtime_call_wasm(exec_env, func, 0, args) ) {
      /* the return value is stored in argv[0] */
      printf("main function returned\n");
    }
    else {
      /* exception is thrown if call fails */
      printf("%s\n", wasm_runtime_get_exception(module_inst));
    }
    wasm_runtime_destroy();    

    return 0;
}