Skip to content

Latest commit

 

History

History
71 lines (49 loc) · 4.59 KB

HOWTO-BINDINGS.md

File metadata and controls

71 lines (49 loc) · 4.59 KB

An elementary guide to using wasm2lua's binder, lua-webidl

What does it do?

It takes in .idl files (in a special interface language) and converts it into .cpp files (and internally a block of lua code) of functions that convert lua calls into C/C++ calls.

Right now, only C/C++ is supported.

Why do we need it?

To simplify the process of porting native code to Lua, and to generate (memory and logic) SAFE code without too much effort.

So how do I use it?

lua-webidl --help

ok, how do i really use it?

sigh here we go...

The module structure

The Lua files generated by wasm2lua in binding generator mode will add in an extra block (and populate the module.bindings table). These functions are auto generated and should be SAFE to call. They are type checked.

Before calling any function, you MUST call module.init().

Classes can also go in module.bindings. Classes are initiated by calling the class table as a function (e.g. module.bindings.ClassName(arg1,arg2)).

Modifications to WebIDL

WebIDL is obviously not designed for Lua, so we had to make some modifications to it. Mainly, WebIDL was augmented with lots of prefixes. They are used by writing prefix operations in square brackets, with occasional arguments for each prefix. WebIDL also has different typenames to C/C++.

NB: classes defined in WebIDL are always pointers to that class when used as arguments/returns. Using [Ref] on those classes makes them double pointers

Here is a list of the type name mapping:

WebIDL C/C++ Notes
octet unsigned char / uint8_t
byte char / int8_t
unsigned short unsigned short int
long int
boolean bool
DOMString char* This has special bindings that auto convert args/returns to regular lua strings. Only works with NULL TERMINATED strings.
any void*
VoidPtr void*

Here are a list of all prefixes:

WebIDL Prefix Argument Notes
Array Integer, length of array It converts the suffix type to an array of that type. Useful for non-null terminated strings.
ArrayLength String, name of array argument It automatically extracts the length of the array (when both the arraylength suffix and array suffix are arguments) and removes the arraylength argument. (i.e. you should not supply it when calling the binding function) MUST use with suffix type any
ArrayRef see Array same as Array, except adds a * (pointer) to the suffix type
ArrayLengthRef see ArrayLength same as ArrayLength, but expects the argument to point to an ArrayRef argument
ConvertInputArray none Converts the input argument using metatable magic to be an internal WASM array. It means that the data is not stored in Lua, but rather in WASM memory. Use with care. Useful when an argument modifies an input variable as its output.
Enum string, name of enum type Turns the suffix argument into an enum type. Suffix argument must be the any type
Size none Turns the suffix argument into a size_t. Suffix argument must be the any type
Const none Adds const to the suffix argument
Ref none Makes the suffix argument a pointer
Value none Makes the suffix argument a value type (dereferences it if applicable)
ToWASMOwned none Compiler hint that the argument/return will be freed by C/C++ code.
ToLuaOwned none Compiler hint that the argument/return will be freed when no Lua code references it. (using __gc)
NoDelete none Compiler hint that even if an argument/return is owned by Lua, it MUST not be freed (disables automatic frees via __gc)
OverrideCanWrite none Makes the suffix argument (for attributes) writable, regardless of whether it was readonly. This exists due to a webidl limitation

Good-To-Know stuff

  • For [Array], we actually copy all lua values into WASM memory and create a duplicate instance in WASM memory. This means that modifications that WASM makes to the array will not be directly transferred back to lua UNLESS [ConvertInputArray] is used
  • For most cases, any libraries you use will not have a main() function because they're libraries (duh). So, lua-webidl has --libmode which generates a stub main function and initialises libc for you. This stub function is used in module.init(), and this is why it's important to call that function.
  • namespace global {} will actually reference the global C/C++ namespace. Using this, you can bind C libraries which populate their functions into the global C namespace. Otherwise, namespaces are analogous to C++ namespaces and can be used to reference a C++ namespace. When generating bindings, functions/classes inside a namespace will be put inside a Lua table. (e.g. module.bindings.namespaceName.funcName)