|
| 1 | +/** |
| 2 | + * @file |
| 3 | + * @brief Ecsact System Implementation with WebAssembly header |
| 4 | + */ |
| 5 | + |
| 6 | +#ifndef ECSACT_SI_WASM_H |
| 7 | +#define ECSACT_SI_WASM_H |
| 8 | + |
| 9 | +#include "ecsact/runtime/common.h" |
| 10 | + |
| 11 | +#ifndef ECSACT_SI_WASM_API_FN |
| 12 | +# if defined(ECSACT_SI_WASM_API) |
| 13 | +# define ECSACT_SI_WASM_API_FN(ret, name) ECSACT_SI_WASM_API ret name |
| 14 | +# elif defined(ECSACT_SI_WASM_API_LOAD_AT_RUNTIME) |
| 15 | +# if defined(ECSACT_SI_WASM_API_EXPORT) |
| 16 | +# define ECSACT_SI_WASM_API_FN(ret, name) \ |
| 17 | + ECSACT_EXTERN ECSACT_EXPORT(#name) ret(*name) |
| 18 | +# else |
| 19 | +# define ECSACT_SI_WASM_API_FN(ret, name) \ |
| 20 | + ECSACT_EXTERN ECSACT_IMPORT("env", #name) ret(*name) |
| 21 | +# endif |
| 22 | +# elif defined(ECSACT_SI_WASM_API_EXPORT) |
| 23 | +# define ECSACT_SI_WASM_API_FN(ret, name) \ |
| 24 | + ECSACT_EXTERN ECSACT_EXPORT(#name) ret name |
| 25 | +# else |
| 26 | +# define ECSACT_SI_WASM_API_FN(ret, name) \ |
| 27 | + ECSACT_EXTERN ECSACT_IMPORT("env", #name) ret name |
| 28 | +# endif |
| 29 | +#endif // ECSACT_SI_WASM_API_FN |
| 30 | + |
| 31 | +typedef enum ecsact_si_wasm_error { |
| 32 | + /** |
| 33 | + * No error. |
| 34 | + */ |
| 35 | + ECSACT_SI_WASM_OK, |
| 36 | + |
| 37 | + /** |
| 38 | + * Unable to open WASM file. |
| 39 | + */ |
| 40 | + ECSACT_SI_WASM_ERR_FILE_OPEN_FAIL, |
| 41 | + |
| 42 | + /** |
| 43 | + * Unable to read WASM file. |
| 44 | + */ |
| 45 | + ECSACT_SI_WASM_ERR_FILE_READ_FAIL, |
| 46 | + |
| 47 | + /** |
| 48 | + * Unable to compile WASM file module. |
| 49 | + */ |
| 50 | + ECSACT_SI_WASM_ERR_COMPILE_FAIL, |
| 51 | + |
| 52 | + /** |
| 53 | + * Unable to instantiate WASM file module. |
| 54 | + */ |
| 55 | + ECSACT_SI_WASM_ERR_INSTANTIATE_FAIL, |
| 56 | + |
| 57 | + /** |
| 58 | + * Export name was not found in WASM file. |
| 59 | + */ |
| 60 | + ECSACT_SI_WASM_ERR_EXPORT_NOT_FOUND, |
| 61 | + |
| 62 | + /** |
| 63 | + * Export name was found, but was not a function. |
| 64 | + */ |
| 65 | + ECSACT_SI_WASM_ERR_EXPORT_INVALID, |
| 66 | + |
| 67 | + /** |
| 68 | + * WASM file contains an unknown guest import. |
| 69 | + */ |
| 70 | + ECSACT_SI_WASM_ERR_GUEST_IMPORT_UNKNOWN, |
| 71 | + |
| 72 | + /** |
| 73 | + * WASM file contains correctly named guest import, but was not a function |
| 74 | + */ |
| 75 | + ECSACT_SI_WASM_ERR_GUEST_IMPORT_INVALID, |
| 76 | + |
| 77 | + /** |
| 78 | + * Invoking `_initialize()` resulted in a wasm trap |
| 79 | + */ |
| 80 | + ECSACT_SI_WASM_ERR_INITIALIZE_FAIL, |
| 81 | + |
| 82 | + /** |
| 83 | + * Ecsact dynamic module is 'load at runtime' but |
| 84 | + * 'ecsact_set_system_execution_impl' has not been set. |
| 85 | + */ |
| 86 | + ECSACT_SI_WASM_ERR_NO_SET_SYSTEM_EXECUTION, |
| 87 | +} ecsact_si_wasm_error; |
| 88 | + |
| 89 | +ECSACT_SI_WASM_API_FN(void, ecsact_si_wasm_last_error_message) |
| 90 | +( // |
| 91 | + char* out_message, |
| 92 | + int32_t out_message_max_length |
| 93 | +); |
| 94 | + |
| 95 | +ECSACT_SI_WASM_API_FN(int32_t, ecsact_si_wasm_last_error_message_length)(); |
| 96 | + |
| 97 | +/** |
| 98 | + * Load WASM file at path `wasm_file_path` and call |
| 99 | + * `ecsact_set_system_execution_impl` for the specified `system_ids` matching |
| 100 | + * the `wasm_exports` names. |
| 101 | + * @param wasm_file_path path to WASM file |
| 102 | + * @param systems_count Length of `system_ids` and `wasm_exports` |
| 103 | + * @param system_ids Sequential array of system ids that will have their system |
| 104 | + * implementations set to by the wasm exports dicated by `wasm_exports` |
| 105 | + * in the same order. Length is determined by `systems_count`. |
| 106 | + * @param wasm_exports Sequential array of wasm export names used as system |
| 107 | + * implementations in the same order as `system_ids`. Length is |
| 108 | + * determined by `systems_count`. |
| 109 | + * @return `ECSACT_SI_WASM_OK` if no error. If there is an error for _any_ of |
| 110 | + * the systems then **none of the systems are loaded**. |
| 111 | + */ |
| 112 | +ECSACT_SI_WASM_API_FN(ecsact_si_wasm_error, ecsact_si_wasm_load_file) |
| 113 | +( // |
| 114 | + const char* wasm_file_path, |
| 115 | + int systems_count, |
| 116 | + ecsact_system_like_id* system_ids, |
| 117 | + const char** wasm_exports |
| 118 | +); |
| 119 | + |
| 120 | +ECSACT_SI_WASM_API_FN(ecsact_si_wasm_error, ecsact_si_wasm_load) |
| 121 | +( // |
| 122 | + char* wasm_data, |
| 123 | + int wasm_data_size, |
| 124 | + int systems_count, |
| 125 | + ecsact_system_like_id* system_ids, |
| 126 | + const char** wasm_exports |
| 127 | +); |
| 128 | + |
| 129 | +/** |
| 130 | + * Unload 1 or more systems. If a system is not already loaded this is a noop. |
| 131 | + * @param systems_count number of systems impls to unload |
| 132 | + * @param system_ids array of system IDs to unload. Sequential list length of |
| 133 | + * @p systems_count. |
| 134 | + */ |
| 135 | +ECSACT_SI_WASM_API_FN(void, ecsact_si_wasm_unload) |
| 136 | +( // |
| 137 | + int systems_count, |
| 138 | + ecsact_system_like_id* system_ids |
| 139 | +); |
| 140 | + |
| 141 | +/** |
| 142 | + * Reset state. Effectively called `ecsact_si_wasm_unload` for each system |
| 143 | + * implementation and clears the trap handler. |
| 144 | + */ |
| 145 | +ECSACT_SI_WASM_API_FN(void, ecsact_si_wasm_reset)(); |
| 146 | + |
| 147 | +/** |
| 148 | + * @param system_id System ID associated with the impl that triggered the trap |
| 149 | + * @param trap_message The trap message contents. Null-terminated string. |
| 150 | + */ |
| 151 | +typedef void (*ecsact_si_wasm_trap_handler)( // |
| 152 | + ecsact_system_like_id system_id, |
| 153 | + const char* trap_message |
| 154 | +); |
| 155 | + |
| 156 | +/** |
| 157 | + * Register a function to be called when a system implementation trap occurs. It |
| 158 | + * is recommended that a trap handler is set otherwise the trap message will be |
| 159 | + * quietly discarded. |
| 160 | + * @param handler The handler function that will be called when a system impl |
| 161 | + * function trap occurs. Calling this overwrites the last handler. May be |
| 162 | + * `NULL` to remove the current handler. |
| 163 | + */ |
| 164 | +ECSACT_SI_WASM_API_FN(void, ecsact_si_wasm_set_trap_handler) |
| 165 | +( // |
| 166 | + ecsact_si_wasm_trap_handler handler |
| 167 | +); |
| 168 | + |
| 169 | +typedef enum ecsact_si_wasm_log_level { |
| 170 | + ECSACT_SI_WASM_LOG_LEVEL_INFO = 0, |
| 171 | + ECSACT_SI_WASM_LOG_LEVEL_WARNING = 1, |
| 172 | + ECSACT_SI_WASM_LOG_LEVEL_ERROR = 2, |
| 173 | +} ecsact_si_wasm_log_level; |
| 174 | + |
| 175 | +typedef void (*ecsact_si_wasm_log_consumer)( // |
| 176 | + ecsact_si_wasm_log_level log_level, |
| 177 | + const char* message, |
| 178 | + int32_t message_length, |
| 179 | + void* user_data |
| 180 | +); |
| 181 | + |
| 182 | +/** |
| 183 | + * Invokes @p consumer for 1 or more lines that have been printed to stdout or |
| 184 | + * stderr between the last `ecsact_si_wasm_consume_logs` call until there are no |
| 185 | + * more lines left to consume. |
| 186 | + */ |
| 187 | +ECSACT_SI_WASM_API_FN(void, ecsact_si_wasm_consume_logs) |
| 188 | +( // |
| 189 | + ecsact_si_wasm_log_consumer consumer, |
| 190 | + void* consumer_user_data |
| 191 | +); |
| 192 | + |
| 193 | +/** |
| 194 | + * Expose a file on the host for read access during initialization. |
| 195 | + */ |
| 196 | +ECSACT_SI_WASM_API_FN(int32_t, ecsact_si_wasm_allow_file_read_access) |
| 197 | +( // |
| 198 | + const char* real_file_path, |
| 199 | + int32_t real_file_path_length, |
| 200 | + const char* virtual_file_path, |
| 201 | + int32_t virtual_file_path_length |
| 202 | +); |
| 203 | + |
| 204 | +// # BEGIN FOR_EACH_ECSACT_SI_WASM_API_FN |
| 205 | +#ifdef ECSACT_MSVC_TRADITIONAL |
| 206 | +# define FOR_EACH_ECSACT_SI_WASM_API_FN(fn, ...) \ |
| 207 | + ECSACT_MSVC_TRADITIONAL_ERROR() |
| 208 | +#else |
| 209 | +# define FOR_EACH_ECSACT_SI_WASM_API_FN(fn, ...) \ |
| 210 | + fn(ecsact_si_wasm_last_error_message, __VA_ARGS__); \ |
| 211 | + fn(ecsact_si_wasm_last_error_message_length, __VA_ARGS__); \ |
| 212 | + fn(ecsact_si_wasm_load_file, __VA_ARGS__); \ |
| 213 | + fn(ecsact_si_wasm_load, __VA_ARGS__); \ |
| 214 | + fn(ecsact_si_wasm_unload, __VA_ARGS__); \ |
| 215 | + fn(ecsact_si_wasm_reset, __VA_ARGS__); \ |
| 216 | + fn(ecsact_si_wasm_set_trap_handler, __VA_ARGS__); \ |
| 217 | + fn(ecsact_si_wasm_consume_logs, __VA_ARGS__); \ |
| 218 | + fn(ecsact_si_wasm_allow_file_read_access, __VA_ARGS__) |
| 219 | +#endif |
| 220 | + |
| 221 | +#endif // ECSACT_SI_WASM_H |
0 commit comments