-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enhance documents #25
Open
TianlongLiang
wants to merge
1
commit into
web-devkits:main
Choose a base branch
from
TianlongLiang:dev/update_doc
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,10 @@ | ||
# Embed compiled native object file in C/C++ | ||
# Embed compiled native object file guideline | ||
|
||
From the previous documentation on how to [compile Wasm to native](./compile_wasm_app_to_native.md), 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](../samples/embed-compiled-native/)) | ||
From the previous documentation on how to [compile Wasm to native](./compile_wasm_app_to_native.md), we have seen how to compile the wasm app to a native object file, then linking it with the auxiliary library, both in `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 embed the static library and shared library linked from the native object file and auxiliary library within your application. | ||
|
||
The complete sample code can be found in this [directory](../samples/embed-compiled-native/). | ||
|
||
## Wasm app is compiled to native in sandbox mode | ||
|
||
|
@@ -13,11 +17,11 @@ The sandbox mode is the default mode when compiling the wasm app to native. As i | |
|
||
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: | ||
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, link with source files like `wasm_application.c` and `main.c` to generate an executable file as the final product, or link without them to generate a library as the final product. | ||
|
||
### 1. Link with source files like `wasm_application.c` and `main.c` to generate an executable file as the final product | ||
### Choice one: 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](./compile_wasm_app_to_native.md), 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` . | ||
As we can see in [compile wasm applications to native binary](./compile_wasm_app_to_native.md), 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. | ||
|
||
|
@@ -36,7 +40,7 @@ webassembly> add 3 4 | |
|
||
For more details, you can refer to the [this section](./compile_wasm_app_to_native.md#binary-executable). | ||
|
||
### 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 | ||
### Choice two: 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. | ||
|
||
|
@@ -106,3 +110,127 @@ gcc -O3 -o nosandbox_with_staticlib ../src/nosandbox_main.c -L. -lstaticnosandbo | |
# Example usage of executable, in the nosandbox_main.c it calls the add function in the wasm object file | ||
./nosandbox_with_staticlib | ||
``` | ||
|
||
## General workflow of embedding wasm object file generated library | ||
|
||
In the previous two sections, we have seen how to use the final product of the wasm app compiled to native in sandbox mode and no-sandbox mode. Here we will explore more details of the general workflow of embedding the wasm final product library in the host native binary. | ||
|
||
For the **no-sandbox mode** library, use the library as you would use a normal library, for example, in your wasm application you will make a library as the final product, and you can have such function: | ||
|
||
```C | ||
// wasm app C source | ||
int | ||
add(int a, int b) | ||
{ | ||
return a + b; | ||
} | ||
``` | ||
|
||
Then in your host native binary, you can call this function directly. | ||
|
||
```C | ||
#include <stdio.h> | ||
|
||
extern int | ||
add(int a, int b); | ||
|
||
int | ||
main() | ||
{ | ||
printf("Nosandbox main: add 3 + 4 = %d\n", add(3, 4)); | ||
} | ||
``` | ||
|
||
So in this section, we will focus on the sandbox mode library. | ||
|
||
Here is the more detailed process of how to use the export APIs defined in `w2n_export.h` to interact with the wasm app(in the form of a library) in the host native binary: | ||
|
||
### Embed the wasm app library in the host native binary | ||
|
||
First, the wasm instance needs to be created using `wasm_instance_create()`, and check whether it creates successfully using `wasm_instance_is_created()`. If it fails or at the end of the host native binary, we need to destroy the wasm instance. | ||
|
||
```C | ||
wasm_instance_create(); | ||
if (!wasm_instance_is_created()) { | ||
os_printf("Create wasm instance failed.\n"); | ||
goto fail; | ||
} | ||
|
||
... | ||
|
||
fail: | ||
wasm_instance_destroy(); | ||
return ret; | ||
``` | ||
|
||
Then you can use `wasm_get_export_apis()` and `wasm_get_export_api_num()` to get and call the wasm function by name, following similar procedures as below(a full example process can be found in `execute_func` of [wasm_application.c](wasm2native-vmlib/application/wasm_application.c)): | ||
|
||
```C | ||
WASMExportApi *export_apis = wasm_get_export_apis(); | ||
WASMExportApi *export_func = NULL; | ||
void (*invoke_native)(const void *, uint32 *, uint32 *); | ||
uint32 export_api_num = wasm_get_export_api_num(); | ||
|
||
/* Lookup exported function */ | ||
for (i = 0; i < export_api_num; i++) { | ||
if (!strcmp(export_apis[i].func_name, name)) { | ||
export_func = &export_apis[i]; | ||
break; | ||
} | ||
} | ||
|
||
/* from the export_func->signature, parse and prepare the arguments array(argv1) */ | ||
... | ||
|
||
/* lookup the quick aot entry, basically it will reinterpret the function ptr type that will match export_func->signature */ | ||
invoke_native = lookup_quick_aot_entry(export_func->signature); | ||
|
||
/* call the wasm function, use the argv1 as both parameter and return array */ | ||
invoke_native(export_func->func_ptr, argv1, argv1); | ||
|
||
/* parse and process the return value from the return array(argv1) */ | ||
... | ||
``` | ||
|
||
PS: during the wasm instance creation or calling the wasm function, you can use `wasm_get_exception()` and `wasm_get_exception_msg()` to check the exception and utilize the exception message. | ||
|
||
```C | ||
static void | ||
check_and_print_exception() | ||
{ | ||
int32 exce_id = wasm_get_exception(); | ||
const char*exce_msg; | ||
if (exce_id) { | ||
exce_msg = wasm_get_exception_msg(); | ||
os_printf("Exception: %s\n", exce_msg); | ||
} | ||
else { | ||
os_printf("Exception: unknown error\n"); | ||
} | ||
} | ||
|
||
// check whether create wasm instance successfully | ||
int | ||
main(int argc, char *argv[]) | ||
{ | ||
... | ||
|
||
if (!wasm_instance_is_created()) { | ||
os_printf("Create wasm instance failed.\n"); | ||
check_and_print_exception(); | ||
goto fail; | ||
} | ||
|
||
... | ||
|
||
if (!app_instance_func(func_name)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't call app_instance_func, it is also provided in wasm_application.c and suppose not to be linked in some scenarios. |
||
ret = 1; | ||
|
||
if (ret) { | ||
check_and_print_exception(); | ||
} | ||
|
||
... | ||
|
||
} | ||
``` |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lookup_quick_aot_entry is provided by wasm_application.c and is static. Developer must link the libcvmlib.a, but we suppose that he doesn't have to link it.
Suggest to just convert the func_ptr to an function according the prototype, and call it directly, like: