callback.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <inttypes.h>
  5. #include "wasm_c_api.h"
  6. #define own
  7. // Print a Wasm value
  8. void wasm_val_print(wasm_val_t val) {
  9. switch (val.kind) {
  10. case WASM_I32: {
  11. printf("%" PRIu32, val.of.i32);
  12. } break;
  13. case WASM_I64: {
  14. printf("%" PRIu64, val.of.i64);
  15. } break;
  16. case WASM_F32: {
  17. printf("%f", val.of.f32);
  18. } break;
  19. case WASM_F64: {
  20. printf("%g", val.of.f64);
  21. } break;
  22. case WASM_EXTERNREF:
  23. case WASM_FUNCREF: {
  24. if (val.of.ref == NULL) {
  25. printf("null");
  26. } else {
  27. printf("ref(%p)", val.of.ref);
  28. }
  29. } break;
  30. }
  31. }
  32. // A function to be called from Wasm code.
  33. own wasm_trap_t* print_callback(
  34. const wasm_val_vec_t* args, wasm_val_vec_t* results
  35. ) {
  36. printf("Calling back...\n> ");
  37. wasm_val_print(args->data[0]);
  38. printf("\n");
  39. wasm_val_copy(&results->data[0], &args->data[0]);
  40. return NULL;
  41. }
  42. // A function closure.
  43. own wasm_trap_t* closure_callback(
  44. void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results
  45. ) {
  46. int i = *(int*)env;
  47. printf("Calling back closure...\n");
  48. printf("> %d\n", i);
  49. results->data[0].kind = WASM_I32;
  50. results->data[0].of.i32 = (int32_t)i;
  51. return NULL;
  52. }
  53. int main(int argc, const char* argv[]) {
  54. // Initialize.
  55. printf("Initializing...\n");
  56. wasm_engine_t* engine = wasm_engine_new();
  57. wasm_store_t* store = wasm_store_new(engine);
  58. // Load binary.
  59. printf("Loading binary...\n");
  60. #if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0
  61. FILE* file = fopen("callback.aot", "rb");
  62. #else
  63. FILE* file = fopen("callback.wasm", "rb");
  64. #endif
  65. if (!file) {
  66. printf("> Error loading module!\n");
  67. return 1;
  68. }
  69. int ret = fseek(file, 0L, SEEK_END);
  70. if (ret == -1) {
  71. printf("> Error loading module!\n");
  72. fclose(file);
  73. return 1;
  74. }
  75. long file_size = ftell(file);
  76. if (file_size == -1) {
  77. printf("> Error loading module!\n");
  78. fclose(file);
  79. return 1;
  80. }
  81. ret = fseek(file, 0L, SEEK_SET);
  82. if (ret == -1) {
  83. printf("> Error loading module!\n");
  84. fclose(file);
  85. return 1;
  86. }
  87. wasm_byte_vec_t binary;
  88. wasm_byte_vec_new_uninitialized(&binary, file_size);
  89. if (fread(binary.data, file_size, 1, file) != 1) {
  90. printf("> Error loading module!\n");
  91. fclose(file);
  92. return 1;
  93. }
  94. fclose(file);
  95. // Compile.
  96. printf("Compiling module...\n");
  97. own wasm_module_t* module = wasm_module_new(store, &binary);
  98. if (!module) {
  99. printf("> Error compiling module!\n");
  100. return 1;
  101. }
  102. wasm_byte_vec_delete(&binary);
  103. // Create external print functions.
  104. printf("Creating callback...\n");
  105. own wasm_functype_t* print_type = wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32());
  106. own wasm_func_t* print_func = wasm_func_new(store, print_type, print_callback);
  107. int i = 42;
  108. own wasm_functype_t* closure_type = wasm_functype_new_0_1(wasm_valtype_new_i32());
  109. own wasm_func_t* closure_func = wasm_func_new_with_env(store, closure_type, closure_callback, &i, NULL);
  110. wasm_functype_delete(print_type);
  111. wasm_functype_delete(closure_type);
  112. // Instantiate.
  113. printf("Instantiating module...\n");
  114. wasm_extern_t* externs[] = {
  115. wasm_func_as_extern(print_func), wasm_func_as_extern(closure_func)
  116. };
  117. wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
  118. own wasm_instance_t* instance =
  119. wasm_instance_new(store, module, &imports, NULL);
  120. if (!instance) {
  121. printf("> Error instantiating module!\n");
  122. return 1;
  123. }
  124. wasm_func_delete(print_func);
  125. wasm_func_delete(closure_func);
  126. // Extract export.
  127. printf("Extracting export...\n");
  128. own wasm_extern_vec_t exports;
  129. wasm_instance_exports(instance, &exports);
  130. if (exports.size == 0) {
  131. printf("> Error accessing exports!\n");
  132. return 1;
  133. }
  134. const wasm_func_t* run_func = wasm_extern_as_func(exports.data[0]);
  135. if (run_func == NULL) {
  136. printf("> Error accessing export!\n");
  137. return 1;
  138. }
  139. wasm_module_delete(module);
  140. wasm_instance_delete(instance);
  141. // Call.
  142. printf("Calling export...\n");
  143. wasm_val_t as[2] = { WASM_I32_VAL(3), WASM_I32_VAL(4) };
  144. wasm_val_t rs[1] = { WASM_INIT_VAL };
  145. wasm_val_vec_t args = WASM_ARRAY_VEC(as);
  146. wasm_val_vec_t results = WASM_ARRAY_VEC(rs);
  147. wasm_trap_t *trap = wasm_func_call(run_func, &args, &results);
  148. if (trap) {
  149. printf("> Error calling function!\n");
  150. wasm_trap_delete(trap);
  151. return 1;
  152. }
  153. wasm_extern_vec_delete(&exports);
  154. // Print result.
  155. printf("Printing result...\n");
  156. printf("> %u\n", rs[0].of.i32);
  157. // Shut down.
  158. printf("Shutting down...\n");
  159. wasm_store_delete(store);
  160. wasm_engine_delete(engine);
  161. // All done.
  162. printf("Done.\n");
  163. return 0;
  164. }