Implement more wasm-c-apis and enable Envoy integration (#622)
Implement more wasm-c-api APIs to support Envoy integration: - sync up with latest c-api definition - change CMakeLists to export necessary headers and install the static library of iwasm - enable to export tables and memories - support memorytype and tabletype APIs - update wasm-c-api sampels - enable to export importtype APIs And refine bazel scripts for sample XNNPACK workload, add license headers for sample simple. Signed-off-by: Wenyong Huang <wenyong.huang@intel.com>
This commit is contained in:
202
samples/wasm-c-api/src/LICENSE
Normal file
202
samples/wasm-c-api/src/LICENSE
Normal file
@ -0,0 +1,202 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
@ -4,14 +4,6 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "wasm_c_api.h"
|
||||
#include "wasm_export.h"
|
||||
#include "bh_platform.h"
|
||||
|
||||
extern bool
|
||||
reader(const char *module_name, uint8 **p_buffer, uint32 *p_size);
|
||||
|
||||
extern void
|
||||
destroyer(uint8 *buffer, uint32 size);
|
||||
|
||||
#define own
|
||||
|
||||
@ -69,8 +61,6 @@ own wasm_trap_t* closure_callback(
|
||||
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
wasm_runtime_set_module_reader(reader, destroyer);
|
||||
|
||||
// Initialize.
|
||||
printf("Initializing...\n");
|
||||
wasm_engine_t* engine = wasm_engine_new();
|
||||
@ -78,11 +68,7 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
// Load binary.
|
||||
printf("Loading binary...\n");
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0
|
||||
FILE* file = fopen("callback.aot", "rb");
|
||||
#else
|
||||
FILE* file = fopen("callback.wasm", "rb");
|
||||
#endif
|
||||
if (!file) {
|
||||
printf("> Error loading module!\n");
|
||||
return 1;
|
||||
@ -154,12 +140,8 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
// Call.
|
||||
printf("Calling export...\n");
|
||||
wasm_val_t args[2];
|
||||
args[0].kind = WASM_I32;
|
||||
args[0].of.i32 = 3;
|
||||
args[1].kind = WASM_I32;
|
||||
args[1].of.i32 = 4;
|
||||
wasm_val_t results[1];
|
||||
wasm_val_t args[2] = { WASM_I32_VAL(3), WASM_I32_VAL(4) };
|
||||
wasm_val_t results[1] = { WASM_INIT_VAL };
|
||||
if (wasm_func_call(run_func, args, results)) {
|
||||
printf("> Error calling function!\n");
|
||||
return 1;
|
||||
|
||||
@ -4,14 +4,6 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "wasm_c_api.h"
|
||||
#include "wasm_export.h"
|
||||
#include "bh_platform.h"
|
||||
|
||||
extern bool
|
||||
reader(const char *module_name, uint8 **p_buffer, uint32 *p_size);
|
||||
|
||||
extern void
|
||||
destroyer(uint8 *buffer, uint32 size);
|
||||
|
||||
#define own
|
||||
|
||||
@ -54,8 +46,6 @@ wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) {
|
||||
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
wasm_runtime_set_module_reader(reader, destroyer);
|
||||
|
||||
// Initialize.
|
||||
printf("Initializing...\n");
|
||||
wasm_engine_t* engine = wasm_engine_new();
|
||||
@ -63,11 +53,7 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
// Load binary.
|
||||
printf("Loading binary...\n");
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0
|
||||
FILE* file = fopen("global.aot", "rb");
|
||||
#else
|
||||
FILE* file = fopen("global.wasm", "rb");
|
||||
#endif
|
||||
if (!file) {
|
||||
printf("> Error loading module!\n");
|
||||
return 1;
|
||||
@ -104,16 +90,16 @@ int main(int argc, const char* argv[]) {
|
||||
own wasm_globaltype_t* var_i64_type = wasm_globaltype_new(
|
||||
wasm_valtype_new(WASM_I64), WASM_VAR);
|
||||
|
||||
wasm_val_t val_f32_1 = {.kind = WASM_F32, .of = {.f32 = 1}};
|
||||
wasm_val_t val_f32_1 = WASM_F32_VAL(1);
|
||||
own wasm_global_t* const_f32_import =
|
||||
wasm_global_new(store, const_f32_type, &val_f32_1);
|
||||
wasm_val_t val_i64_2 = {.kind = WASM_I64, .of = {.i64 = 2}};
|
||||
wasm_val_t val_i64_2 = WASM_I64_VAL(2);
|
||||
own wasm_global_t* const_i64_import =
|
||||
wasm_global_new(store, const_i64_type, &val_i64_2);
|
||||
wasm_val_t val_f32_3 = {.kind = WASM_F32, .of = {.f32 = 3}};
|
||||
wasm_val_t val_f32_3 = WASM_F32_VAL(3);
|
||||
own wasm_global_t* var_f32_import =
|
||||
wasm_global_new(store, var_f32_type, &val_f32_3);
|
||||
wasm_val_t val_i64_4 = {.kind = WASM_I64, .of = {.i64 = 4}};
|
||||
wasm_val_t val_i64_4 = WASM_I64_VAL(4);
|
||||
own wasm_global_t* var_i64_import =
|
||||
wasm_global_new(store, var_i64_type, &val_i64_4);
|
||||
|
||||
@ -189,13 +175,13 @@ int main(int argc, const char* argv[]) {
|
||||
check_call(get_var_i64_export, i64, 8);
|
||||
|
||||
// Modify variables through API and check again.
|
||||
wasm_val_t val33 = {.kind = WASM_F32, .of = {.f32 = 33}};
|
||||
wasm_val_t val33 = WASM_F32_VAL(33);
|
||||
wasm_global_set(var_f32_import, &val33);
|
||||
wasm_val_t val34 = {.kind = WASM_I64, .of = {.i64 = 34}};
|
||||
wasm_val_t val34 = WASM_I64_VAL(34);
|
||||
wasm_global_set(var_i64_import, &val34);
|
||||
wasm_val_t val37 = {.kind = WASM_F32, .of = {.f32 = 37}};
|
||||
wasm_val_t val37 = WASM_F32_VAL(37);
|
||||
wasm_global_set(var_f32_export, &val37);
|
||||
wasm_val_t val38 = {.kind = WASM_I64, .of = {.i64 = 38}};
|
||||
wasm_val_t val38 = WASM_I64_VAL(38);
|
||||
wasm_global_set(var_i64_export, &val38);
|
||||
|
||||
check_global(var_f32_import, f32, 33);
|
||||
@ -209,13 +195,13 @@ int main(int argc, const char* argv[]) {
|
||||
check_call(get_var_i64_export, i64, 38);
|
||||
|
||||
// Modify variables through calls and check again.
|
||||
wasm_val_t args73[] = { {.kind = WASM_F32, .of = {.f32 = 73}} };
|
||||
wasm_val_t args73[] = { WASM_F32_VAL(73) };
|
||||
wasm_func_call(set_var_f32_import, args73, NULL);
|
||||
wasm_val_t args74[] = { {.kind = WASM_I64, .of = {.i64 = 74}} };
|
||||
wasm_val_t args74[] = { WASM_I64_VAL(74) };
|
||||
wasm_func_call(set_var_i64_import, args74, NULL);
|
||||
wasm_val_t args77[] = { {.kind = WASM_F32, .of = {.f32 = 77}} };
|
||||
wasm_val_t args77[] = { WASM_F32_VAL(77) };
|
||||
wasm_func_call(set_var_f32_export, args77, NULL);
|
||||
wasm_val_t args78[] = { {.kind = WASM_I64, .of = {.i64 = 78}} };
|
||||
wasm_val_t args78[] = { WASM_I64_VAL(78) };
|
||||
wasm_func_call(set_var_i64_export, args78, NULL);
|
||||
|
||||
check_global(var_f32_import, f32, 73);
|
||||
|
||||
@ -4,14 +4,6 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "wasm_c_api.h"
|
||||
#include "wasm_export.h"
|
||||
#include "bh_platform.h"
|
||||
|
||||
extern bool
|
||||
reader(const char *module_name, uint8 **p_buffer, uint32 *p_size);
|
||||
|
||||
extern void
|
||||
destroyer(uint8 *buffer, uint32 size);
|
||||
|
||||
#define own
|
||||
|
||||
@ -26,8 +18,6 @@ own wasm_trap_t* hello_callback(
|
||||
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
wasm_runtime_set_module_reader(reader, destroyer);
|
||||
|
||||
// Initialize.
|
||||
printf("Initializing...\n");
|
||||
wasm_engine_t* engine = wasm_engine_new();
|
||||
@ -35,11 +25,7 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
// Load binary.
|
||||
printf("Loading binary...\n");
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0
|
||||
FILE* file = fopen("hello.aot", "rb");
|
||||
#else
|
||||
FILE* file = fopen("hello.wasm", "rb");
|
||||
#endif
|
||||
if (!file) {
|
||||
printf("> Error loading module!\n");
|
||||
return 1;
|
||||
@ -65,26 +51,15 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
wasm_byte_vec_delete(&binary);
|
||||
|
||||
// Create external print functions.
|
||||
printf("Creating callback...\n");
|
||||
own wasm_functype_t* hello_type = wasm_functype_new_0_0();
|
||||
own wasm_func_t* hello_func =
|
||||
wasm_func_new(store, hello_type, hello_callback);
|
||||
|
||||
wasm_functype_delete(hello_type);
|
||||
|
||||
// Instantiate.
|
||||
printf("Instantiating module...\n");
|
||||
const wasm_extern_t* imports[] = { wasm_func_as_extern(hello_func) };
|
||||
own wasm_instance_t* instance =
|
||||
wasm_instance_new(store, module, imports, NULL);
|
||||
wasm_instance_new(store, module, NULL, NULL);
|
||||
if (!instance) {
|
||||
printf("> Error instantiating module!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_func_delete(hello_func);
|
||||
|
||||
// Extract export.
|
||||
printf("Extracting export...\n");
|
||||
own wasm_extern_vec_t exports;
|
||||
@ -93,22 +68,10 @@ int main(int argc, const char* argv[]) {
|
||||
printf("> Error accessing exports!\n");
|
||||
return 1;
|
||||
}
|
||||
const wasm_func_t* run_func = wasm_extern_as_func(exports.data[0]);
|
||||
if (run_func == NULL) {
|
||||
printf("> Error accessing export!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_module_delete(module);
|
||||
wasm_instance_delete(instance);
|
||||
|
||||
// Call.
|
||||
printf("Calling export...\n");
|
||||
if (wasm_func_call(run_func, NULL, NULL)) {
|
||||
printf("> Error calling function!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_extern_vec_delete(&exports);
|
||||
|
||||
// Shut down.
|
||||
|
||||
153
samples/wasm-c-api/src/multi.c
Normal file
153
samples/wasm-c-api/src/multi.c
Normal file
@ -0,0 +1,153 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "wasm_c_api.h"
|
||||
|
||||
#define own
|
||||
|
||||
// A function to be called from Wasm code.
|
||||
own wasm_trap_t* callback(
|
||||
const wasm_val_t args[], wasm_val_t results[]
|
||||
) {
|
||||
printf("Calling back...\n> ");
|
||||
printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n",
|
||||
args[0].of.i32, args[1].of.i64,
|
||||
args[2].of.i64, args[3].of.i32);
|
||||
printf("\n");
|
||||
|
||||
wasm_val_copy(&results[0], &args[3]);
|
||||
wasm_val_copy(&results[1], &args[1]);
|
||||
wasm_val_copy(&results[2], &args[2]);
|
||||
wasm_val_copy(&results[3], &args[0]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// A function closure.
|
||||
own wasm_trap_t* closure_callback(
|
||||
void* env, const wasm_val_t args[], wasm_val_t results[]
|
||||
) {
|
||||
int i = *(int*)env;
|
||||
printf("Calling back closure...\n");
|
||||
printf("> %d\n", i);
|
||||
|
||||
results[0].kind = WASM_I32;
|
||||
results[0].of.i32 = (int32_t)i;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
// Initialize.
|
||||
printf("Initializing...\n");
|
||||
wasm_engine_t* engine = wasm_engine_new();
|
||||
wasm_store_t* store = wasm_store_new(engine);
|
||||
|
||||
// Load binary.
|
||||
printf("Loading binary...\n");
|
||||
FILE* file = fopen("multi.wasm", "rb");
|
||||
if (!file) {
|
||||
printf("> Error loading module!\n");
|
||||
return 1;
|
||||
}
|
||||
fseek(file, 0L, SEEK_END);
|
||||
size_t file_size = ftell(file);
|
||||
fseek(file, 0L, SEEK_SET);
|
||||
wasm_byte_vec_t binary;
|
||||
wasm_byte_vec_new_uninitialized(&binary, file_size);
|
||||
if (fread(binary.data, file_size, 1, file) != 1) {
|
||||
printf("> Error loading module!\n");
|
||||
return 1;
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
// Compile.
|
||||
printf("Compiling module...\n");
|
||||
own wasm_module_t* module = wasm_module_new(store, &binary);
|
||||
if (!module) {
|
||||
printf("> Error compiling module!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_byte_vec_delete(&binary);
|
||||
|
||||
// Create external print functions.
|
||||
printf("Creating callback...\n");
|
||||
wasm_valtype_t* types[4] = {
|
||||
wasm_valtype_new_i32(), wasm_valtype_new_i64(),
|
||||
wasm_valtype_new_i64(), wasm_valtype_new_i32()
|
||||
};
|
||||
own wasm_valtype_vec_t tuple1, tuple2;
|
||||
wasm_valtype_vec_new(&tuple1, 4, types);
|
||||
wasm_valtype_vec_copy(&tuple2, &tuple1);
|
||||
own wasm_functype_t* callback_type = wasm_functype_new(&tuple1, &tuple2);
|
||||
own wasm_func_t* callback_func =
|
||||
wasm_func_new(store, callback_type, callback);
|
||||
|
||||
wasm_functype_delete(callback_type);
|
||||
|
||||
// Instantiate.
|
||||
printf("Instantiating module...\n");
|
||||
const wasm_extern_t* imports[] = { wasm_func_as_extern(callback_func) };
|
||||
own wasm_instance_t* instance =
|
||||
wasm_instance_new(store, module, imports, NULL);
|
||||
if (!instance) {
|
||||
printf("> Error instantiating module!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_func_delete(callback_func);
|
||||
|
||||
// Extract export.
|
||||
printf("Extracting export...\n");
|
||||
own wasm_extern_vec_t exports;
|
||||
wasm_instance_exports(instance, &exports);
|
||||
if (exports.size == 0) {
|
||||
printf("> Error accessing exports!\n");
|
||||
return 1;
|
||||
}
|
||||
const wasm_func_t* run_func = wasm_extern_as_func(exports.data[0]);
|
||||
if (run_func == NULL) {
|
||||
printf("> Error accessing export!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_module_delete(module);
|
||||
wasm_instance_delete(instance);
|
||||
|
||||
// Call.
|
||||
printf("Calling export...\n");
|
||||
wasm_val_t args[4] = {
|
||||
WASM_I32_VAL(1), WASM_I64_VAL(2), WASM_I64_VAL(3), WASM_I32_VAL(4)
|
||||
};
|
||||
wasm_val_t results[4] = {
|
||||
WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL
|
||||
};
|
||||
if (wasm_func_call(run_func, args, results)) {
|
||||
printf("> Error calling function!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_extern_vec_delete(&exports);
|
||||
|
||||
// Print result.
|
||||
printf("Printing result...\n");
|
||||
printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n",
|
||||
results[0].of.i32, results[1].of.i64, results[2].of.i64, results[3].of.i32);
|
||||
|
||||
assert(results[0].of.i32 == 1);
|
||||
assert(results[1].of.i64 == 2);
|
||||
assert(results[2].of.i64 == 3);
|
||||
assert(results[3].of.i32 == 4);
|
||||
|
||||
// Shut down.
|
||||
printf("Shutting down...\n");
|
||||
wasm_store_delete(store);
|
||||
wasm_engine_delete(engine);
|
||||
|
||||
// All done.
|
||||
printf("Done.\n");
|
||||
return 0;
|
||||
}
|
||||
7
samples/wasm-c-api/src/multi.wat
Normal file
7
samples/wasm-c-api/src/multi.wat
Normal file
@ -0,0 +1,7 @@
|
||||
(module
|
||||
(func $f (import "" "f") (param i32 i64 i64 i32) (result i32 i64 i64 i32))
|
||||
|
||||
(func $g (export "g") (param i32 i64 i64 i32) (result i32 i64 i64 i32)
|
||||
(call $f (local.get 0) (local.get 2) (local.get 1) (local.get 3))
|
||||
)
|
||||
)
|
||||
170
samples/wasm-c-api/src/reflect.c
Normal file
170
samples/wasm-c-api/src/reflect.c
Normal file
@ -0,0 +1,170 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "wasm_c_api.h"
|
||||
|
||||
#define own
|
||||
|
||||
void print_mutability(wasm_mutability_t mut) {
|
||||
switch (mut) {
|
||||
case WASM_VAR: printf("var"); break;
|
||||
case WASM_CONST: printf("const"); break;
|
||||
}
|
||||
}
|
||||
|
||||
void print_limits(const wasm_limits_t* limits) {
|
||||
printf("%ud", limits->min);
|
||||
if (limits->max < wasm_limits_max_default) printf(" %ud", limits->max);
|
||||
}
|
||||
|
||||
void print_valtype(const wasm_valtype_t* type) {
|
||||
switch (wasm_valtype_kind(type)) {
|
||||
case WASM_I32: printf("i32"); break;
|
||||
case WASM_I64: printf("i64"); break;
|
||||
case WASM_F32: printf("f32"); break;
|
||||
case WASM_F64: printf("f64"); break;
|
||||
case WASM_ANYREF: printf("anyref"); break;
|
||||
case WASM_FUNCREF: printf("funcref"); break;
|
||||
}
|
||||
}
|
||||
|
||||
void print_valtypes(const wasm_valtype_vec_t* types) {
|
||||
bool first = true;
|
||||
for (size_t i = 0; i < types->size; ++i) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
printf(" ");
|
||||
}
|
||||
print_valtype(types->data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void print_externtype(const wasm_externtype_t* type) {
|
||||
switch (wasm_externtype_kind(type)) {
|
||||
case WASM_EXTERN_FUNC: {
|
||||
const wasm_functype_t* functype =
|
||||
wasm_externtype_as_functype_const(type);
|
||||
printf("func ");
|
||||
print_valtypes(wasm_functype_params(functype));
|
||||
printf(" -> ");
|
||||
print_valtypes(wasm_functype_results(functype));
|
||||
} break;
|
||||
case WASM_EXTERN_GLOBAL: {
|
||||
const wasm_globaltype_t* globaltype =
|
||||
wasm_externtype_as_globaltype_const(type);
|
||||
printf("global ");
|
||||
print_mutability(wasm_globaltype_mutability(globaltype));
|
||||
printf(" ");
|
||||
print_valtype(wasm_globaltype_content(globaltype));
|
||||
} break;
|
||||
case WASM_EXTERN_TABLE: {
|
||||
const wasm_tabletype_t* tabletype =
|
||||
wasm_externtype_as_tabletype_const(type);
|
||||
printf("table ");
|
||||
print_limits(wasm_tabletype_limits(tabletype));
|
||||
printf(" ");
|
||||
print_valtype(wasm_tabletype_element(tabletype));
|
||||
} break;
|
||||
case WASM_EXTERN_MEMORY: {
|
||||
const wasm_memorytype_t* memorytype =
|
||||
wasm_externtype_as_memorytype_const(type);
|
||||
printf("memory ");
|
||||
print_limits(wasm_memorytype_limits(memorytype));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void print_name(const wasm_name_t* name) {
|
||||
printf("\"%.*s\"", (int)name->size, name->data);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
// Initialize.
|
||||
printf("Initializing...\n");
|
||||
wasm_engine_t* engine = wasm_engine_new();
|
||||
wasm_store_t* store = wasm_store_new(engine);
|
||||
|
||||
// Load binary.
|
||||
printf("Loading binary...\n");
|
||||
FILE* file = fopen("reflect.wasm", "rb");
|
||||
if (!file) {
|
||||
printf("> Error loading module!\n");
|
||||
return 1;
|
||||
}
|
||||
fseek(file, 0L, SEEK_END);
|
||||
size_t file_size = ftell(file);
|
||||
fseek(file, 0L, SEEK_SET);
|
||||
wasm_byte_vec_t binary;
|
||||
wasm_byte_vec_new_uninitialized(&binary, file_size);
|
||||
if (fread(binary.data, file_size, 1, file) != 1) {
|
||||
printf("> Error loading module!\n");
|
||||
return 1;
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
// Compile.
|
||||
printf("Compiling module...\n");
|
||||
own wasm_module_t* module = wasm_module_new(store, &binary);
|
||||
if (!module) {
|
||||
printf("> Error compiling module!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_byte_vec_delete(&binary);
|
||||
|
||||
// Instantiate.
|
||||
printf("Instantiating module...\n");
|
||||
own wasm_instance_t* instance =
|
||||
wasm_instance_new(store, module, NULL, NULL);
|
||||
if (!instance) {
|
||||
printf("> Error instantiating module!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Extract export.
|
||||
printf("Extracting export...\n");
|
||||
own wasm_exporttype_vec_t export_types;
|
||||
own wasm_extern_vec_t exports;
|
||||
wasm_module_exports(module, &export_types);
|
||||
wasm_instance_exports(instance, &exports);
|
||||
assert(exports.size == export_types.size);
|
||||
|
||||
for (size_t i = 0; i < exports.size; ++i) {
|
||||
assert(wasm_extern_kind(exports.data[i]) ==
|
||||
wasm_externtype_kind(wasm_exporttype_type(export_types.data[i])));
|
||||
printf("> export %zu ", i);
|
||||
print_name(wasm_exporttype_name(export_types.data[i]));
|
||||
printf("\n");
|
||||
printf(">> initial: ");
|
||||
print_externtype(wasm_exporttype_type(export_types.data[i]));
|
||||
printf("\n");
|
||||
printf(">> current: ");
|
||||
own wasm_externtype_t* current = wasm_extern_type(exports.data[i]);
|
||||
print_externtype(current);
|
||||
wasm_externtype_delete(current);
|
||||
printf("\n");
|
||||
if (wasm_extern_kind(exports.data[i]) == WASM_EXTERN_FUNC) {
|
||||
wasm_func_t* func = wasm_extern_as_func(exports.data[i]);
|
||||
printf(">> in-arity: %zu", wasm_func_param_arity(func));
|
||||
printf(", out-arity: %zu\n", wasm_func_result_arity(func));
|
||||
}
|
||||
}
|
||||
|
||||
wasm_module_delete(module);
|
||||
wasm_instance_delete(instance);
|
||||
wasm_extern_vec_delete(&exports);
|
||||
wasm_exporttype_vec_delete(&export_types);
|
||||
|
||||
// Shut down.
|
||||
printf("Shutting down...\n");
|
||||
wasm_store_delete(store);
|
||||
wasm_engine_delete(engine);
|
||||
|
||||
// All done.
|
||||
printf("Done.\n");
|
||||
return 0;
|
||||
}
|
||||
6
samples/wasm-c-api/src/reflect.wat
Normal file
6
samples/wasm-c-api/src/reflect.wat
Normal file
@ -0,0 +1,6 @@
|
||||
(module
|
||||
(func (export "func") (param i32 f64 f32) (result i32) (unreachable))
|
||||
(global (export "global") f64 (f64.const 0))
|
||||
(table (export "table") 0 50 anyfunc)
|
||||
(memory (export "memory") 1)
|
||||
)
|
||||
124
samples/wasm-c-api/src/trap.c
Normal file
124
samples/wasm-c-api/src/trap.c
Normal file
@ -0,0 +1,124 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "wasm_c_api.h"
|
||||
|
||||
#define own
|
||||
|
||||
// A function to be called from Wasm code.
|
||||
own wasm_trap_t* fail_callback(
|
||||
void* env, const wasm_val_t args[], wasm_val_t results[]
|
||||
) {
|
||||
printf("Calling back...\n");
|
||||
own wasm_name_t message;
|
||||
wasm_name_new_from_string_nt(&message, "callback abort");
|
||||
own wasm_trap_t* trap = wasm_trap_new((wasm_store_t*)env, &message);
|
||||
wasm_name_delete(&message);
|
||||
return trap;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
// Initialize.
|
||||
printf("Initializing...\n");
|
||||
wasm_engine_t* engine = wasm_engine_new();
|
||||
wasm_store_t* store = wasm_store_new(engine);
|
||||
|
||||
// Load binary.
|
||||
printf("Loading binary...\n");
|
||||
FILE* file = fopen("trap.wasm", "rb");
|
||||
if (!file) {
|
||||
printf("> Error loading module!\n");
|
||||
return 1;
|
||||
}
|
||||
fseek(file, 0L, SEEK_END);
|
||||
size_t file_size = ftell(file);
|
||||
fseek(file, 0L, SEEK_SET);
|
||||
wasm_byte_vec_t binary;
|
||||
wasm_byte_vec_new_uninitialized(&binary, file_size);
|
||||
if (fread(binary.data, file_size, 1, file) != 1) {
|
||||
printf("> Error loading module!\n");
|
||||
return 1;
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
// Compile.
|
||||
printf("Compiling module...\n");
|
||||
own wasm_module_t* module = wasm_module_new(store, &binary);
|
||||
if (!module) {
|
||||
printf("> Error compiling module!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_byte_vec_delete(&binary);
|
||||
|
||||
// Create external print functions.
|
||||
printf("Creating callback...\n");
|
||||
own wasm_functype_t* fail_type =
|
||||
wasm_functype_new_0_1(wasm_valtype_new_i32());
|
||||
own wasm_func_t* fail_func =
|
||||
wasm_func_new_with_env(store, fail_type, fail_callback, store, NULL);
|
||||
|
||||
wasm_functype_delete(fail_type);
|
||||
|
||||
// Instantiate.
|
||||
printf("Instantiating module...\n");
|
||||
const wasm_extern_t* imports[] = { wasm_func_as_extern(fail_func) };
|
||||
own wasm_instance_t* instance =
|
||||
wasm_instance_new(store, module, imports, NULL);
|
||||
if (!instance) {
|
||||
printf("> Error instantiating module!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_func_delete(fail_func);
|
||||
|
||||
// Extract export.
|
||||
printf("Extracting exports...\n");
|
||||
own wasm_extern_vec_t exports;
|
||||
wasm_instance_exports(instance, &exports);
|
||||
if (exports.size < 2) {
|
||||
printf("> Error accessing exports!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_module_delete(module);
|
||||
wasm_instance_delete(instance);
|
||||
|
||||
// Call.
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
const wasm_func_t* func = wasm_extern_as_func(exports.data[i]);
|
||||
if (func == NULL) {
|
||||
printf("> Error accessing export!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Calling export %d...\n", i);
|
||||
wasm_val_t results[1]; \
|
||||
own wasm_trap_t* trap = wasm_func_call(func, NULL, results);
|
||||
if (!trap) {
|
||||
printf("> Error calling function, expected trap!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Printing message...\n");
|
||||
own wasm_name_t message;
|
||||
wasm_trap_message(trap, &message);
|
||||
printf("> %s\n", message.data);
|
||||
|
||||
wasm_trap_delete(trap);
|
||||
wasm_name_delete(&message);
|
||||
}
|
||||
|
||||
wasm_extern_vec_delete(&exports);
|
||||
|
||||
// Shut down.
|
||||
printf("Shutting down...\n");
|
||||
wasm_store_delete(store);
|
||||
wasm_engine_delete(engine);
|
||||
|
||||
// All done.
|
||||
printf("Done.\n");
|
||||
return 0;
|
||||
}
|
||||
5
samples/wasm-c-api/src/trap.wat
Normal file
5
samples/wasm-c-api/src/trap.wat
Normal file
@ -0,0 +1,5 @@
|
||||
(module
|
||||
(func $callback (import "" "callback") (result i32))
|
||||
(func (export "callback") (result i32) (call $callback))
|
||||
(func (export "unreachable") (result i32) (unreachable) (i32.const 1))
|
||||
)
|
||||
Reference in New Issue
Block a user