You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
553 lines
22 KiB
Markdown
553 lines
22 KiB
Markdown
# Moon -- A C Binding Toolkit for Lua #
|
|
|
|
This library provides new convenience functions for binding C types to
|
|
Lua as userdata for Lua 5.1, Lua 5.2, and Lua 5.3. It supports objects
|
|
with different lifetimes, polymorphic type checking, type-safe binding
|
|
of tagged unions or embedded structs, properties and methods at the
|
|
same time, and uniform handling of pointers to objects using a simple
|
|
and small set of API functions.
|
|
|
|
|
|
## Using this Library ##
|
|
|
|
This package includes a header file `moon.h` and the corresponding
|
|
source file `moon.c`. To use this package you need to include the
|
|
header file wherever you want to call one of the macros/functions
|
|
defined within. If you just have a single source file where you want
|
|
to use those functions, you are done: `moon.h` includes `moon.c` and
|
|
makes every function `static`. If you have multiple source files that
|
|
need functions/macros from this library, this approach is flawed,
|
|
because you will end up with multiple versions of the same functions.
|
|
Instead include the header wherever you need it, but when you compile
|
|
those source files, define the macro `MOON_PREFIX` to a unique name
|
|
to use for all functions in the `moon` library. You also have to
|
|
compile and link `moon.c` using the same define. This approach will
|
|
change the common `moon_` prefix to your custom prefix behind the
|
|
scenes to avoid linker errors in case another library also links to
|
|
`moon.c`.
|
|
The header file `moon_flag.h` can be included whenever needed, but it
|
|
depends on the functions defined in `moon.c`. The `moon_dlfix.h`
|
|
header is completely independent, but relies on some platform specific
|
|
functions.
|
|
|
|
|
|
## Reference ##
|
|
|
|
This section lists all provided macros/functions.
|
|
|
|
|
|
### `moon.h`/`moon.c` ###
|
|
|
|
The main part of the moon toolkit.
|
|
|
|
|
|
#### `MOON_EXPORT`, `MOON_IMPORT`, `MOON_LOCAL` ####
|
|
|
|
#define MOON_EXPORT
|
|
#define MOON_IMPORT
|
|
#define MOON_LOCAL
|
|
|
|
Macros for specifying symbol visibility.
|
|
|
|
|
|
#### `MOON_CONCAT` ####
|
|
|
|
#define MOON_CONCAT( _a, _b )
|
|
|
|
A macro that evaluates both arguments and joins them together. You can
|
|
use that to build valid C identifiers with custom prefixes or
|
|
suffixes.
|
|
|
|
|
|
#### `MOON_STRINGIFY` ####
|
|
|
|
#define MOON_STRINGIFY( _v )
|
|
|
|
A macro that has the same effect as `#_v`, but works outside of a
|
|
macro substitution.
|
|
|
|
|
|
#### `moon_object_header` ####
|
|
|
|
typedef struct {
|
|
unsigned char flags;
|
|
unsigned char cleanup_offset;
|
|
unsigned char vcheck_offset;
|
|
unsigned char object_offset;
|
|
} moon_object_header;
|
|
|
|
Common data structure shared by all userdata objects created via the
|
|
moon toolkit. The object may have optional fields following the memory
|
|
of this header structure, stored at the given offsets. The `flags`
|
|
field is a bit mask describing the details of the object. A pointer to
|
|
this header can be obtained by using plain `lua_touserdata` on a moon
|
|
object.
|
|
|
|
|
|
#### `moon_object_cast` ####
|
|
|
|
typedef void* (*moon_object_cast)( void* );
|
|
|
|
Function pointer type for conversion functions used by `moon_defcast`.
|
|
|
|
|
|
#### `moon_object_destructor` ####
|
|
|
|
typedef void (*moon_object_destructor)( void* );
|
|
|
|
Function pointer type for cleanup functions of moon objects.
|
|
|
|
|
|
#### `MOON_OBJECT_IS_VALID`, `MOON_OBJECT_IS_POINTER` ####
|
|
|
|
#define MOON_OBJECT_IS_VALID 0x01
|
|
#define MOON_OBJECT_IS_POINTER 0x02
|
|
|
|
Values stored in the `flags` field of the `moon_object_header`
|
|
structure. The only value interesting for users of the library is the
|
|
`MOON_OBJECT_IS_VALID` flag which is reset automatically by the
|
|
`moon_killobject` function to signal that the destructor has already
|
|
run.
|
|
|
|
|
|
#### `moon_defobject` ####
|
|
|
|
/* [ -nup, +0, e ] */
|
|
void moon_defobject( lua_State* L,
|
|
char const* metatable_name,
|
|
size_t userdata_size,
|
|
luaL_Reg const* methods,
|
|
int nup );
|
|
|
|
This function creates a new metatable and registers the functions in
|
|
the `luaL_Reg` array (functions starting with double underscores `__`
|
|
go into the metatable, functions starting with a fullstop `.` are
|
|
setup as properties, and the rest goes into a table used by the
|
|
`__index` metafield). Property functions act as `__index` and
|
|
`__newindex` functions at the same time, i.e. they should return a
|
|
value when called with two arguments, and assign the third value when
|
|
called with three. If the `luaL_Reg` array also contains an `__index`
|
|
and/or `__newindex` function, those functions are called as fallbacks
|
|
when method/property lookup has failed. In case a metatable with the
|
|
given name already exists, an error is raised. The `userdata_size` is
|
|
stored in the metatable for the `moon_newobject` function -- use a
|
|
size of 0 to prohibit use of `moon_newobject` (e.g. for incomplete
|
|
types). If `nup` is non-zero, it pops those upvalues from the current
|
|
Lua stack top and makes them available to all registered functions
|
|
(metamethods, property functions, *and* methods). A `__gc` metamethod
|
|
and a default `__tostring` metamethod are provided by `moon_defobject`
|
|
as well.
|
|
|
|
|
|
#### `moon_newobject` ####
|
|
|
|
/* [ -0, +1, e ] */
|
|
void* moon_newobject( lua_State* L,
|
|
char const* metatable_name,
|
|
moon_object_destructor destructor );
|
|
|
|
This function allocates a userdata, sets a metatable, and stores the
|
|
cleanup function for later use by the `__gc` metamethod or the
|
|
`moon_killobject` function. It throws an error if the `metatable_name`
|
|
has not been registered via the `moon_defobject` function. The new
|
|
userdata object is pushed to the top of the Lua stack, and a pointer
|
|
to the payload (*not* the `moon_object_header` structure) is returned.
|
|
|
|
|
|
#### `moon_newpointer` ####
|
|
|
|
/* [ -0, +1, e ] */
|
|
void** moon_newpointer( lua_State* L,
|
|
char const* metatable_name,
|
|
moon_object_destructor destructor );
|
|
|
|
This function allocates a userdata suitable for storing a pointer,
|
|
sets a metatable, and stores the cleanup function for later use by the
|
|
`__gc` metamethod or the `moon_killobject` function. It is equivalent
|
|
to `moon_newobject` with the difference that the payload is stored as
|
|
a pointer, not inside the userdata memory. The pointer is initialized
|
|
to `NULL` when this function returns, and may be set by assigning to
|
|
the memory location pointed to by the return value.
|
|
|
|
|
|
#### `moon_newfield` ####
|
|
|
|
/* [ -0, +1, e ] */
|
|
void** moon_newfield( lua_State* L,
|
|
char const* metatable_name,
|
|
int idx,
|
|
int (*isvalid)( void* p ),
|
|
void* p );
|
|
|
|
This function allocates a userdata suitable for storing a pointer, and
|
|
sets a metatable. It is similar to `moon_newpointer`, but it is
|
|
intended for exposing a data structure embedded within another
|
|
userdata (referenced by stack position `idx`). The resulting moon
|
|
object keeps the parent userdata alive by storing a reference in its
|
|
uservalue table. If `idx` is `0`, no uservalue table is set. Setting a
|
|
cleanup function is not possible, because the parent userdata is
|
|
responsible for cleaning up memory and other resources.
|
|
If an `isvalid` function pointer is provided, it is called by the
|
|
`moon_checkobject`/`moon_testobject` functions to check whether the
|
|
object is still valid. This can be used to make sure that a tagged
|
|
union used as parent userdata still has the correct type, or that the
|
|
parent userdata hasn't released any necessary resources prior to
|
|
garbage collection. If the value referenced by `idx` is a moon object
|
|
that also has an `isvalid` check registered, all checks are performed
|
|
in the order from parent object(s) to child object.
|
|
|
|
|
|
#### `moon_getmethods` ####
|
|
|
|
/* [ -0, +(0|1), e ] */
|
|
int moon_getmethods( lua_State* L,
|
|
char const* tname );
|
|
|
|
If the metatable identified by `tname` has methods registered, pushes
|
|
the methods table and returns `LUA_TTABLE`. Otherwise nothing is
|
|
pushed and `LUA_TNIL` is returned. This function only works for moon
|
|
objects and raises an error if the metatable `tname` wasn't registered
|
|
via `moon_defobject`.
|
|
|
|
|
|
#### `moon_killobject` ####
|
|
|
|
/* [ -0, +0, e ] */
|
|
void moon_killobject( lua_State* L,
|
|
int idx );
|
|
|
|
If the moon object at the given stack index is valid, its cleanup
|
|
function is run, and the object is marked as invalid (to prevent the
|
|
cleanup function from running again). This function can be used to
|
|
reclaim resources before the object becomes unreachable.
|
|
|
|
|
|
#### `moon_defcast` ####
|
|
|
|
/* [ -0, +0, e ] */
|
|
void moon_defcast( lua_State* L,
|
|
char const* tname1,
|
|
char const* tname2,
|
|
moon_object_cast cast );
|
|
|
|
Registers the conversion function `cast` for converting userdata
|
|
objects of type `tname1` to type `tname2`. The `cast` function is
|
|
called automatically by `moon_checkobject( L, idx, tname2 )` when
|
|
applied to an object of type `tname1`, so function implementations can
|
|
be reused without extra work. The metatable `tname1` must already
|
|
exist and belong to a moon object type (created via `moon_defobject`).
|
|
|
|
|
|
#### `moon_checkobject` ####
|
|
|
|
/* [ -0, +0, v ] */
|
|
void* moon_checkobject( lua_State* L,
|
|
int idx,
|
|
char const* metatable_name );
|
|
|
|
This function ensures that the value stored at stack index `idx`
|
|
|
|
1. is a full userdata
|
|
2. is a moon object
|
|
3. has the metatable identified by `metatable_name` or has a
|
|
cast function to `metatable_name` registered
|
|
4. has the `MOON_OBJECT_IS_VALID` flag set
|
|
5. all `isvalid` functions return a non-zero value (for objects
|
|
created via `moon_newfield`)
|
|
6. contains a non-`NULL` pointer value (for objects created via
|
|
`moon_newpointer` or `moon_newfield`).
|
|
|
|
If any of those conditions are false, an error is raised. Otherwise
|
|
this function returns a pointer to the object's memory (meaning the
|
|
objects created via `moon_newpointer` and `moon_newfield` are
|
|
dereferenced once, and if necessary the registered cast function is
|
|
called).
|
|
|
|
|
|
#### `moon_testobject` ####
|
|
|
|
/* [ -0, +0, e ] */
|
|
void* moon_testobject( lua_State* L,
|
|
int idx,
|
|
char const* metatable_name );
|
|
|
|
Performs the same checks as `moon_checkobject`, but returns `NULL` if
|
|
any of those conditions are false instead of raising an error.
|
|
|
|
|
|
#### `moon_checkint` ####
|
|
|
|
/* [ -0, +0, v ] */
|
|
lua_Integer moon_checkint( lua_State* L,
|
|
int idx,
|
|
lua_Integer min,
|
|
lua_Integer max );
|
|
|
|
This function works like `luaL_checkinteger` but additionally ensures
|
|
that the given value is in the range [`min`, `max`], or else an error
|
|
is thrown.
|
|
|
|
|
|
#### `moon_optint` ####
|
|
|
|
/* [ -0, +0, v ] */
|
|
lua_Integer moon_optint( lua_State* L,
|
|
int idx,
|
|
lua_Integer min,
|
|
lua_Integer max,
|
|
lua_Integer def );
|
|
|
|
Similar to `moon_checkint` but uses the default value `def` if the
|
|
value at the given stack position is `nil` or `none`.
|
|
|
|
|
|
#### `moon_atexit` ####
|
|
|
|
/* [ -0, +1, e ] */
|
|
int* moon_atexit( lua_State* L,
|
|
lua_CFunction cleanup );
|
|
|
|
This function puts an integer-sized userdata (initialized to 0) in the
|
|
registry and sets the given `cleanup` function as `__gc` metamethod.
|
|
The userdata is also pushed to the top of the Lua stack, and returned
|
|
as an `int` pointer.
|
|
Use this function if you want to call a cleanup function when the Lua
|
|
state is closed, but only if some initialization succeeded. The usual
|
|
approach is as follows:
|
|
|
|
1. Call `moon_atexit` registering your cleanup function.
|
|
2. Do your initialization.
|
|
3. If successful, you set the `int` pointer to non-zero, which is
|
|
almost atomic and can't fail, and pop the userdata.
|
|
4. When the cleanup function is called, check for a non-zero value
|
|
before actually cleaning up.
|
|
|
|
|
|
#### `moon_setuvfield` ####
|
|
|
|
/* [ -1, +0, e ] */
|
|
void moon_setuvfield( lua_State* L,
|
|
int idx,
|
|
char const* key );
|
|
|
|
This function pops the value at the top of the stack and stores it
|
|
under `key` in the environment/uservalue table of the object at stack
|
|
position `idx`.
|
|
|
|
|
|
#### `moon_getuvfield` ####
|
|
|
|
/* [ -0, +(0|1), e ] */
|
|
int moon_getuvfield( lua_State* L,
|
|
int idx,
|
|
char const* key );
|
|
|
|
This function works similar to `luaL_getmetafield`, but it looks for
|
|
`key` in the environment/uservalue table of the object at index `idx`,
|
|
and pushes the corresponding value to the top of the stack. If there
|
|
is no uservalue table or no such field, nothing is pushed and
|
|
`LUA_TNIL` is returned. Otherwise, the return value is the type of the
|
|
pushed value.
|
|
|
|
|
|
#### `moon_getcache` ####
|
|
|
|
/* [ -0, +1, e ] */
|
|
void moon_getcache( lua_State* L,
|
|
int idx );
|
|
|
|
This function looks up and pushes a weak-valued table under a private
|
|
key in the table given by index `idx` (often `LUA_REGISTRYINDEX`). If
|
|
the weak-valued table doesn't exist yet, it is created automatically.
|
|
This function is useful to map lightuserdata to full userdata, but it
|
|
can also be used to cache full userdata for enum values (using
|
|
separate caches per enum type), etc.
|
|
|
|
|
|
#### `moon_stack_assert` ####
|
|
|
|
/* [ -0, +0, v ] */
|
|
void moon_stack_assert( lua_State* L,
|
|
... );
|
|
|
|
This "function" is implemented as a macro that evaluates to `void` if
|
|
`NDEBUG` is defined. If it is not, it tries to match the type
|
|
specifications (strings) given as arguments to the values at the top
|
|
of the Lua stack. Every mismatch is reported on `stderr`, and finally
|
|
the whole Lua stack is dumped to `stderr` using the `moon_stack`
|
|
function below, and an error is raised. Currently the following type
|
|
specifications are supported:
|
|
|
|
* `"n"`: nil
|
|
* `"b"`: boolean
|
|
* `"l"`: lightuserdata
|
|
* `"i"`: integer (equivalent to `"d"` before Lua 5.3)
|
|
* `"d"`: number (think `double`)
|
|
* `"s"`: string
|
|
* `"t"`: table
|
|
* `"f"`: function
|
|
* `"u"`: userdata
|
|
* `"c"`: coroutine
|
|
* `"a"`: any (non-nil) value
|
|
|
|
You can combine the single letter options to express alternatives, so
|
|
e.g. `"tf"` means: table or function.
|
|
|
|
|
|
#### `moon_stack` ####
|
|
|
|
/* [ -0, +0, - ] */
|
|
void moon_stack( lua_State* L );
|
|
|
|
This "function" is also implemented as a macro that evaluates to
|
|
`void` in case `NDEBUG` is defined. Otherwise it prints the current
|
|
contents of the Lua stack in human-readable format to `stderr`.
|
|
|
|
|
|
#### `moon_absindex` ####
|
|
|
|
Compatiblity macro for `lua_absindex`, but also available on Lua 5.1
|
|
as a function.
|
|
|
|
|
|
#### `moon_derive` ####
|
|
|
|
int moon_derive( lua_State* L );
|
|
|
|
A `lua_CFunction` that may be registered as part of your module and
|
|
allows Lua code to subclass a moon object. When called it expects two
|
|
strings as arguments: a new (non-existing) type name and an old
|
|
(existing) type name of a moon object type. It sets up the new type
|
|
name as an alias to the old type but with a different methods table.
|
|
The new methods table (initially a copy of the methods of the old
|
|
type) is returned.
|
|
|
|
|
|
#### `moon_downcast` ####
|
|
|
|
int moon_downcast( lua_State* L );
|
|
|
|
A `lua_CFunction` that may be registered as part of your module and
|
|
allows Lua code to change the type of a moon object to a type created
|
|
via `moon_derive`. It is typically used in constructors of derived
|
|
types, and expects a moon object and the new type name as arguments.
|
|
If successful, the object (with its metatable replaced) is returned.
|
|
|
|
|
|
### `moon_flag.h` ###
|
|
|
|
`moon_flag.h` is a macro file, that can be included multiple times and
|
|
each time defines a new userdata type as a type-safe representation of
|
|
a given enum/flag type in Lua. The resulting userdata values support
|
|
`+` (bitwise or, in Lua 5.3 also `|`), `-` (create a new value with
|
|
certain bits cleared), and calling (test if all bits are set). For Lua
|
|
5.3 also bitwise "and" and bitwise "not" are defined.
|
|
Parameters are passed as macros before including the macro file. Any
|
|
arguments and all internal macros are `#undef`ed before leaving the
|
|
macro file. The following parameters are recognized:
|
|
|
|
* `MOON_FLAG_NAME` (required): A metatable name used for defining a
|
|
userdata type.
|
|
* `MOON_FLAG_TYPE` (required): The underlying enum/flag type that is
|
|
handled by the custom userdata.
|
|
* `MOON_FLAG_SUFFIX` (required): All defined functions have this
|
|
suffix (and the `moon_flag_` prefix) to make them unique.
|
|
* `MOON_FLAG_NOBITOPS` (optional): If this macro is defined, no
|
|
metamethods for bitwise operations are created. This includes
|
|
`__add`, `__sub`, and `__call` metamethods. If you do this, you
|
|
should think about using strings and `luaL_checkoption` instead of
|
|
userdata for representing your flags in Lua.
|
|
* `MOON_FLAG_NORELOPS` (optional): If this macro is defined, the
|
|
`__eq` metamethod is not created.
|
|
* `MOON_FLAG_USECACHE` (optional): The constructor function for this
|
|
flag looks in a local cache before creating a new full userdata,
|
|
and returns the cached value if possible. This way each enum/flag
|
|
value has at most one userdata associated with it.
|
|
* `MOON_FLAG_EQMETHOD( _a, _b )` (optional): If you need a custom
|
|
comparison operation instead of the usual `==`, define this macro.
|
|
|
|
The following (static) functions will be defined, unless they are
|
|
disabled via one of the parameter macros above:
|
|
|
|
/* [ -0, +0, e ] */
|
|
void moon_flag_def_SUFFIX( lua_State* L );
|
|
/* [ -0, +1, e ] */
|
|
void moon_flag_new_SUFFIX( lua_State* L, TYPE value );
|
|
/* [ -0, +0, v ] */
|
|
TYPE moon_flag_get_SUFFIX( lua_State* L, int idx );
|
|
|
|
int moon_flag_add_SUFFIX( lua_State* L );
|
|
int moon_flag_sub_SUFFIX( lua_State* L );
|
|
int moon_flag_call_SUFFIX( lua_State* L );
|
|
int moon_flag_and_SUFFIX( lua_State* L ); /* Lua 5.3+ */
|
|
int moon_flag_not_SUFFIX( lua_State* L ); /* Lua 5.3+ */
|
|
int moon_flag_eq_SUFFIX( lua_State* L );
|
|
|
|
The last six are metamethods and not supposed to be called from C.
|
|
`moon_flag_def_SUFFIX` defines the new type, creates the metatable and
|
|
registers all metamethods. `moon_flag_new_SUFFIX` pushes a userdata
|
|
representing the given value to the top of the Lua stack, while
|
|
`moon_flag_get_SUFFIX` returns the corresponding enum value from a
|
|
userdata on the Lua stack (or raises an error).
|
|
|
|
|
|
### `moon_dlfix.h` ###
|
|
|
|
On Linux and BSDs (and possibly other Unix machines) binary extension
|
|
modules aren't linked to the Lua library directly, but instead expect
|
|
the main executable to reexport the Lua API. If you don't have control
|
|
over the main executable (e.g. you are writing a plugin for a 3rd
|
|
party program), you are out of luck. This header file tries to
|
|
reexport the Lua API from the shared library linked to your plugin to
|
|
make it available for extension modules. It relies on some platform
|
|
specific tricks, so it probably won't work everywhere.
|
|
|
|
|
|
#### `MOON_DLFIX` ####
|
|
|
|
#define MOON_DLFIX()
|
|
|
|
This macro uses the dynamic linker to search for the Lua API in an
|
|
already loaded shared library and reexport it for extension modules.
|
|
If the necessary linker tricks don't work on the given platform, this
|
|
macro evaluates to a `void` expression, and you will continue to get
|
|
the usual unresolved symbol errors when loading a binary extension
|
|
module.
|
|
|
|
|
|
#### `MOON_DLFIX_LIBNAME` ####
|
|
|
|
If the builtin heuristics fail to find the shared Lua library you can
|
|
specify the library name/path by defining this macro.
|
|
|
|
|
|
#### `MOON_DLFIX_LIBPREFIX` ####
|
|
|
|
For some OSes *all* loaded shared libraries is searched for an ELF
|
|
object that contains the Lua symbols. Since this procedure also finds
|
|
shared objects that have the Lua library as a dependency, the library
|
|
name is checked for a known prefix to make sure that only the actual
|
|
Lua library is exported. The default is `"liblua"`, but you can change
|
|
it by defining this macro.
|
|
|
|
|
|
## Contact ##
|
|
|
|
Philipp Janda, siffiejoe(a)gmx.net
|
|
|
|
Comments and feedback are always welcome.
|
|
|
|
|
|
## License ##
|
|
|
|
`moon` is *copyrighted free software* distributed under the Tiny
|
|
license. The full license text follows:
|
|
|
|
moon (c) 2013-2016 Philipp Janda
|
|
|
|
You may do anything with this work that copyright law would normally
|
|
restrict, so long as you retain the above notice(s) and this license
|
|
in all redistributed copies and derived works. There is no warranty.
|
|
|
|
|