-
Notifications
You must be signed in to change notification settings - Fork 15
Create Custom Environments
inNative embedding environments are really just standard C libraries that expose their C functions to the WebAssembly modules they are being compiled with. However, inNative also supports creating C libraries that expose WebAssembly-compatible functions by exporting specifically named functions based on the Name Mangling rules.
Compile a static (or shared) library that exports the C functions you want to expose to your WebAssembly modules. If you're using C++, make sure you use extern "C"
to prevent any C++ name-mangling. Then, simply compile your WebAssembly modules while referencing the library.
./innative-cmd.exe your_module.wasm -l your_library.lib
Because Windows generates .lib
files for DLLs, you should do this for either a DLL or a static library.
./innative-cmd your_module.wasm -l your_library.a
./innative-cmd your_module.wasm -L your_shared_library
Linux has a special -L
option that tells it to link against a shared library that should be used. Remember that, in the example above, the real file name would be libyour_shared_library.so
, which is what the linker will look for in the current path. Sometimes the linker can be finicky about library paths, in which case you might want to specify the entire absolute path instead.
If you have followed the instructions above, your C functions can now be imported using the basic C import method:
(import "" "your_function" (func $yourfunc (result i32)))
It's usually a good idea to use the standard C calling convention, but for C functions, you can also use other calling conventions. See Name Mangling for more details on how to call C functions with unusual calling conventions.
It is also possible to create a library that exposes WebAssembly functions, but only if they follow a strict set of rules. The Name Mangling article details how name mangling works for transforming a module + function name pair into a single C symbol: [module]_WASM_[function]
. This mangling can be done in reverse to acquire a WebAssembly module + function name pair out of a C function declaration.
int64_t your_module_WASM_your_function(int64_t a, double b, float c, int32_t d)
{
return 1;
}
Once again, make sure you add extern "C"
if you are working with C++. If you compile a library with this function and add it to the inNative command line when compiling, you will be able to import it into your WebAssembly modules like so:
(import "your_module" "your_function" (func $functest (param i64 f64 f32 i32) (result i64)))
However, some restrictions apply: the function must have a default C calling convention! If it uses any other calling convention, the behavior is undefined and unsafe. In addition, only 5 types can be used:
-
int32_t
<->i32
-
int64_t
<->i64
-
float
<->f32
-
double
<->f64
-
void*
<->i64/i32/cref
Naturally, you can substitute uint32_t
for int32_t
and uint64_t
for int64_t
without a problem. You can also substitute any pointer type for void*
. However, void*
must either be mapped to an i64
on 64-bit architectures, an i32
on 32-bit architectures, or cref
if you want to use inNative's cref extension. Be very careful when matching C function signatures with WebAssembly equivalents, because a mismatched signature can break the sandbox or just crash the program entirely.
Keep in mind that WebAssembly functions trump C functions - if you export a C function masquerading as a WebAssembly import, but another WebAssembly module with the same name and function definition exists, the WebAssembly version wins. Make sure you pick a unique name for your fake module when exporting C functions as WebAssembly imports.