callback_chain.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <inttypes.h>
  9. #include "wasm_c_api.h"
  10. #define own
  11. static const byte_t *
  12. get_memory_data(uint32_t offset, uint32_t length);
  13. static bool
  14. call_wasm_function(uint32_t export_id, const wasm_val_vec_t *args,
  15. wasm_val_vec_t *results, const char *name);
  16. /************************ IMPORTED FUNCTIONS **************************/
  17. // (nil) -> i32
  18. #define FUNCTION_TYPE_NIL_I32 wasm_functype_new_0_1(wasm_valtype_new_i32())
  19. // (i32, i32) -> nil
  20. #define FUNCTION_TYPE_I32X2_NIL \
  21. wasm_functype_new_2_0(wasm_valtype_new_i32(), wasm_valtype_new_i32())
  22. /* IMPORT FUNCTION LIST */
  23. #define IMPORT_FUNCTION_LIST(V) \
  24. V(get_pairs, 0, FUNCTION_TYPE_NIL_I32) \
  25. V(log, 1, FUNCTION_TYPE_I32X2_NIL)
  26. /* EXPORT FUNCTION LIST */
  27. #define EXPORT_FUNCTION_LIST(V) \
  28. V(on_start) \
  29. V(on_stop) \
  30. V(malloc) \
  31. V(free)
  32. enum EXPORT_ITEM_NAME {
  33. #define DEFINE_ENUM(name) e_##name,
  34. EXPORT_FUNCTION_LIST(DEFINE_ENUM)
  35. #undef DEFINE_ENUM
  36. e_MEMORY,
  37. };
  38. #define DEFINE_FUNCTION(name) \
  39. wasm_trap_t *STUB_##name(const wasm_val_vec_t *args, \
  40. wasm_val_vec_t *results)
  41. #define DEFINE_EMPTY_FUNCTION(name) \
  42. DEFINE_FUNCTION(name) \
  43. { \
  44. printf("[WASM -> NATIVE] calling back %s\n", __FUNCTION__); \
  45. return NULL; \
  46. }
  47. #undef DEFINE_EMPTY_FUNCTION
  48. DEFINE_FUNCTION(get_pairs)
  49. {
  50. wasm_val_vec_t as = { 0 };
  51. wasm_val_t data[1] = { WASM_I32_VAL(10) };
  52. wasm_val_vec_new(&as, 1, data);
  53. if (as.data == NULL) {
  54. printf("ERROR: create parameters failed\n");
  55. return NULL;
  56. }
  57. call_wasm_function(e_malloc, &as, results, "malloc");
  58. wasm_val_vec_delete(&as);
  59. return NULL;
  60. }
  61. DEFINE_FUNCTION(log)
  62. {
  63. wasm_val_t offset = args->data[0];
  64. wasm_val_t length = args->data[1];
  65. const byte_t *data = NULL;
  66. printf("[WASM -> NATIVE] calling back %s\n", __FUNCTION__);
  67. if (offset.kind != WASM_I32 || length.kind != WASM_I32) {
  68. printf("> Error value type!\n");
  69. }
  70. if (!(data = get_memory_data(offset.of.i32, length.of.i32))) {
  71. return NULL;
  72. }
  73. if (data[length.of.i32 - 1]) {
  74. printf("> Error terminated character\n");
  75. return NULL;
  76. }
  77. printf("[WASM_LOG] %s\n", data);
  78. return NULL;
  79. }
  80. /**********************************************************************/
  81. // all exportted wasm functions. check with "/opt/wabt/bin/wasm-objdump -x -j
  82. // Export X.wasm" -1: memory 0-32: functions
  83. static own wasm_extern_vec_t exports = { 0 };
  84. static const byte_t *
  85. get_memory_data(uint32_t offset, uint32_t length)
  86. {
  87. wasm_memory_t *memory;
  88. if (!(memory = wasm_extern_as_memory(exports.data[e_MEMORY]))) {
  89. return NULL;
  90. }
  91. byte_t *base = wasm_memory_data(memory);
  92. size_t size = wasm_memory_data_size(memory);
  93. if (!base || offset + length > size) {
  94. return NULL;
  95. }
  96. printf("[NATIVE -> WASM] accessing the memory...\n");
  97. return base + offset;
  98. }
  99. static bool
  100. call_wasm_function(uint32_t export_id, const wasm_val_vec_t *args,
  101. wasm_val_vec_t *results, const char *name)
  102. {
  103. const wasm_func_t *function;
  104. wasm_trap_t *trap;
  105. printf("[NATIVE -> WASM] calling func %s...\n", name);
  106. if (!(function = wasm_extern_as_func(exports.data[export_id]))) {
  107. printf("> Error get export function %u\n", export_id);
  108. return false;
  109. }
  110. if ((trap = wasm_func_call(function, args, results))) {
  111. own wasm_message_t message = { 0 };
  112. wasm_trap_message(trap, &message);
  113. if (message.data) {
  114. printf("> Error calling function %s\n", message.data);
  115. }
  116. else {
  117. printf("> Error calling function");
  118. }
  119. wasm_name_delete(&message);
  120. wasm_trap_delete(trap);
  121. return false;
  122. }
  123. return true;
  124. }
  125. int
  126. main(int argc, const char *argv[])
  127. {
  128. // Initialize.
  129. printf("Initializing...\n");
  130. wasm_engine_t *engine = wasm_engine_new();
  131. wasm_store_t *store = wasm_store_new(engine);
  132. // Load binary.
  133. printf("Loading binary...\n");
  134. #if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0
  135. FILE *file = fopen("callback_chain.aot", "rb");
  136. #else
  137. FILE *file = fopen("callback_chain.wasm", "rb");
  138. #endif
  139. if (!file) {
  140. printf("> Error loading module!\n");
  141. return 1;
  142. }
  143. int ret = fseek(file, 0L, SEEK_END);
  144. if (ret == -1) {
  145. printf("> Error loading module!\n");
  146. fclose(file);
  147. return 1;
  148. }
  149. long file_size = ftell(file);
  150. if (file_size == -1) {
  151. printf("> Error loading module!\n");
  152. fclose(file);
  153. return 1;
  154. }
  155. ret = fseek(file, 0L, SEEK_SET);
  156. if (ret == -1) {
  157. printf("> Error loading module!\n");
  158. fclose(file);
  159. return 1;
  160. }
  161. wasm_byte_vec_t binary;
  162. wasm_byte_vec_new_uninitialized(&binary, file_size);
  163. if (fread(binary.data, file_size, 1, file) != 1) {
  164. printf("> Error loading module!\n");
  165. fclose(file);
  166. return 1;
  167. }
  168. fclose(file);
  169. // Compile.
  170. printf("Compiling module...\n");
  171. own wasm_module_t *module = wasm_module_new(store, &binary);
  172. if (!module) {
  173. printf("> Error compiling module!\n");
  174. return 1;
  175. }
  176. wasm_byte_vec_delete(&binary);
  177. // Instantiate.
  178. printf("Instantiating module...\n");
  179. // Create external functions.
  180. printf("Creating callback...\n");
  181. #define IMPORT_FUNCTION_VARIABLE_NAME(name, ...) \
  182. own wasm_func_t *function_##name = NULL;
  183. IMPORT_FUNCTION_LIST(IMPORT_FUNCTION_VARIABLE_NAME)
  184. #undef IMPORT_FUNCTION_VARIABLE_NAME
  185. #define CREATE_WASM_FUNCTION(name, index, CREATE_FUNC_TYPE) \
  186. { \
  187. own wasm_functype_t *type = CREATE_FUNC_TYPE; \
  188. if (!(function_##name = wasm_func_new(store, type, STUB_##name))) { \
  189. printf("> Error creating new function\n"); \
  190. return 1; \
  191. } \
  192. wasm_functype_delete(type); \
  193. }
  194. IMPORT_FUNCTION_LIST(CREATE_WASM_FUNCTION)
  195. #undef CREATE_WASM_FUNCTION
  196. wasm_extern_t *fs[2] = { 0 };
  197. #define ADD_TO_FUNCTION_LIST(name, index, ...) \
  198. fs[index] = wasm_func_as_extern(function_##name);
  199. IMPORT_FUNCTION_LIST(ADD_TO_FUNCTION_LIST)
  200. #undef ADD_TO_FUNCTION_LIST
  201. wasm_extern_vec_t imports = WASM_ARRAY_VEC(fs);
  202. own wasm_instance_t *instance =
  203. wasm_instance_new(store, module, &imports, NULL);
  204. if (!instance) {
  205. printf("> Error instantiating module!\n");
  206. return 1;
  207. }
  208. #define DESTROY_WASM_FUNCTION(name, index, ...) \
  209. wasm_func_delete(function_##name);
  210. IMPORT_FUNCTION_LIST(DESTROY_WASM_FUNCTION)
  211. #undef DESTROY_WASM_FUNCTION
  212. // Extract export.
  213. printf("Extracting export...\n");
  214. wasm_instance_exports(instance, &exports);
  215. if (!exports.size) {
  216. printf("> Error accessing exports!\n");
  217. return 1;
  218. }
  219. wasm_module_delete(module);
  220. wasm_instance_delete(instance);
  221. // Call.
  222. printf("Calling export...\n");
  223. if (!call_wasm_function(e_on_start, NULL, NULL, "on_start")) {
  224. printf("> Error calling on_start\n");
  225. return 1;
  226. }
  227. if (!call_wasm_function(e_on_stop, NULL, NULL, "on_stop")) {
  228. printf("> Error calling on_stop\n");
  229. return 1;
  230. }
  231. wasm_extern_vec_delete(&exports);
  232. // Shut down.
  233. printf("Shutting down...\n");
  234. wasm_store_delete(store);
  235. wasm_engine_delete(engine);
  236. // All done.
  237. printf("Done.\n");
  238. return 0;
  239. }