quantumde1 2 месяцев назад
Сommit
fe3ff763e9

+ 7 - 0
.gitignore

@@ -0,0 +1,7 @@
+lib
+dub.selections.json
+.dub
+dscanner.ini
+*.kate-swp
+.directory
+.DS_Store

+ 23 - 0
LICENSE_1_0.txt

@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.

+ 173 - 0
README.md

@@ -0,0 +1,173 @@
+# bindbc-lua
+This project provides both static and dynamic bindings to the C API of [Lua programming language](https://www.lua.org/). The bindings are `@nogc` and `nothrow` compatible and can be compiled for compatibility with BetterC. This package is intended as a replacement of [DerelictLua](https://github.com/DerelictOrg/DerelictLua), which is not compatible with `@nogc`,  `nothrow`, or BetterC.
+
+## Usage
+By default, `bindbc-lua` is configured to compile as a dynamic binding that is not BetterC compatible. The dynamic binding has no link-time dependency on the Lua library, so the Lua shared library must be manually loaded at runtime. When configured as a static binding, there is a link-time dependency on the lua library through either the static library or the appropriate file for linking with shared libraries on your platform (see below).
+
+When using DUB to manage your project, the static binding can be enabled via a DUB `subConfiguration` statement in your project's package file. BetterC compatibility is also enabled via subconfigurations.
+
+To use Lua, add `bindbc-lua` as a dependency to your project's package config file. For example, the following is configured to use Lua as a dynamic binding that is not BetterC compatible:
+
+__dub.json__
+```
+dependencies {
+    "bindbc-lua": "~>0.6.0",
+}
+```
+
+__dub.sdl__
+```
+dependency "bindbc-lua" version="~>0.6.0"
+```
+
+### The dynamic binding
+The dynamic binding requires no special configuration when using DUB to manage your project. There is no link-time dependency. At runtime, the Lua shared library is required to be on the shared library search path of the user's system. On Windows, this is typically handled by distributing the Lua DLL with your program. On other systems, it usually means the user must install the Lua library through a package manager.
+
+To load the shared library, you need to call the `loadLua` function. This returns a member of the `LuaSupport` enumeration (See [the README for `bindbc.loader`](https://github.com/BindBC/bindbc-loader/blob/master/README.md) for the error handling API):
+
+* `LuaSupport.noLibrary` indicating that the library failed to load (it couldn't be found)
+* `LuaSupport.badLibrary` indicating that one or more symbols in the library failed to load
+* a member of `LuaSupport` indicating a version number that matches the version of Lua that `bindbc-lua` was configured at compile-time to load. Unlike other BindBC packages, which tend to load the lowest version of a library by default, `binbc-lua` __must__ be configured to load a specific version of the Lua library via a version identifier (see below). This value will match the global manifest constant, `luaSupport`.
+
+```d
+import bindbc.lua;
+
+/*
+This version attempts to load the lua shared library using well-known variations
+of the library name for the host system.
+*/
+LuaSupport ret = loadLua();
+if(ret != luaSupport) {
+
+    // Handle error. For most use cases, its reasonable to use the the error handling API in
+    // bindbc-loader to retrieve error messages for logging and then abort. If necessary, it's
+    // possible to determine the root cause via the return value:
+
+    if(ret == luaSupport.noLibrary) {
+        // Lua shared library failed to load
+    }
+    else if(luaSupport.badLibrary) {
+        // One or more symbols failed to load. The likely cause is that the
+        // shared library is a version different from the one the app was
+        // configured to load
+    }
+}
+/*
+This version attempts to load the Lua library using a user-supplied file name.
+Usually, the name and/or path used will be platform specific, as in this example
+which attempts to load `lua51.dll` from the `libs` subdirectory, relative
+to the executable, only on Windows.
+*/
+// version(Windows) loadLua("libs/lua51.dll")
+```
+Because of the number of changes to Lua's C API between releases, `bindbc-lua` does not attempt to load any version by default as there is no version of the API that is shared by all supported versions of Lua. A specific version of Lua must be specified via the `-version` compiler switch or the `versions` DUB directive with the desired Lua version number. In this example, the Lua dynamic binding is compiled to support Lua 5.1:
+
+__dub.json__
+```
+"dependencies": {
+    "bindbc-lua": "~>0.6.0"
+},
+"versions": ["LUA_51"]
+```
+
+__dub.sdl__
+```
+dependency "bindbc-lua" version="~>0.6.0"
+versions "LUA_51"
+```
+
+With this example configuration, `luaSupport == LuaSupport.lua51`. If Lua 5.1 is installed on the user's system, `loadLua` will return `LuaSupport.lua51`. If no compatible version of Lua is installed, `loadLua` will return `LuaSupport.noLibrary`. The `bindbc-loader` always attempts to load shared libraries with a version number in the name. If the user attempts to load the Lua shared library via an alternative name, it is possible that the binding's configured version and the shared library's actual version do not match, in which case the return value will be `luaSupport.badLibrary`.
+
+The global property `loadedLuaVersion` is an alternative means of testing the result of `loadLua`. With other BindBC bindings, it is possible to load a lower version of a library than the one the binding was configured to load, in which case the global property will indicate the loaded version when the loader returns `badLibrary`. This is not possible in `bindbc-lua`. `loadedLuaVersion` is set to `luaSupport.noLibrary` before `loadLua` is called. When the function returns, `loadedLuaVersion` will be set to the same value as its return value.
+
+The function `isLuaLoaded` returns `true` if the configured version of Lua has been loaded and `false` otherwise.
+
+Following are the supported versions of Lua, the corresponding version IDs to pass to the compiler, and the corresponding `LuaSupport` members.
+
+| Library & Version  | Version ID       | `LuaSupport` Member |
+|--------------------|------------------|---------------------|
+|Lua 5.1             | LUA_51           | `LuaSupport.lua51`  |
+|Lua 5.2             | LUA_52           | `LuaSupport.lua52`  |
+|Lua 5.3             | LUA_53           | `LuaSupport.lua53`  |
+|Lua 5.4             | LUA_54           | `LuaSupport.lua54`  |
+
+## The static binding
+The static binding has a link-time dependency on either the shared or the static Lua library. On Windows, you can link with the static library or, to use the shared library with the import library. On other systems, you can link with either the static library or directly with the shared library. This requires the Lua development package be installed on your system at compile time, either by compiling the Lua source yourself, downloading the Lua precompiled binaries for Windows, or installing via a system package manager.
+
+When linking with the static library, there is no runtime dependency on Lua. When linking with the shared library (or the import library on Windows), the runtime dependency is the same as the dynamic binding, the difference being that the shared library is no longer loaded manually---loading is handled automatically by the system when the program is launched.
+
+Enabling the static binding can be done in two ways.
+
+### Via the compiler's `-version` switch or DUB's `versions` directive
+Pass the `BindLua_Static` version to the compiler and link with the appropriate library. Note that `BindLua_Static` will also enable the static binding for any satellite libraries used.
+
+When using the compiler command line or a build system that doesn't support DUB, this is the only option. The `-version=BindLua_Static` option should be passed to the compiler when building your program. All of the required C libraries, as well as the `bindbc-lua` and `bindbc-loader` static libraries must also be passed to the compiler on the command line or via your build system's configuration.
+
+When using DUB, its `versions` directive is an option. For example, when using the static binding and Lua 5.1:
+
+__dub.json__
+```
+"dependencies": {
+    "bindbc-lua": "~>0.6.0"
+},
+"versions": ["BindLua_Static", "LUA_51"],
+"libs": ["lua5.1"]
+```
+
+__dub.sdl__
+```
+dependency "bindbc-lua" version="~>0.6.0"
+versions "BindLua_Static" "LUA_5.1"
+libs "lua5.1"
+```
+
+### Via DUB subconfigurations
+Instead of using DUB's `versions` directive, a `subConfiguration` can be used. Enable the `static` subconfiguration for the `bindbc-lua` dependency:
+
+__dub.json__
+```
+"dependencies": {
+    "bindbc-lua": "~>0.6.0"
+},
+"subConfigurations": {
+    "bindbc-lua": "static"
+},
+"versions": ["LUA_51"],
+"libs": ["lua5.1"]
+```
+
+__dub.sdl__
+```
+dependency "bindbc-lua" version="~>0.6.0"
+subConfiguration "bindbc-lua" "static"
+versions "LUA_51"
+libs "lua5.1"
+```
+
+This has the benefit that it completely excludes from the build any source modules related to the dynamic binding. (i.e. they will never be passed to the compiler)
+
+## betterc support
+
+betterc support is enabled via the `dynamicBC` and `staticBC` subconfigurations, for dynamic and static bindings respectively. To enable the static binding with BetterC support:
+
+__dub.json__
+```
+"dependencies": {
+    "bindbc-lua": "~>0.6.0"
+},
+"subConfigurations": {
+    "bindbc-lua": "staticBC"
+},
+"versions": ["LUA_51"],
+"libs": ["lua5.1"]
+```
+
+__dub.sdl__
+```
+dependency "bindbc-lua" version="~>0.6.0"
+subConfiguration "bindbc-lua" "staticBC"
+versions "LUA_51"
+libs "lua5.1"
+```
+
+When not using DUB to manage your project, first use DUB to compile the BindBC libraries with the `dynamicBC` or `staticBC` configuration, then pass BetterC to the compiler when building your project.

+ 31 - 0
dub.sdl

@@ -0,0 +1,31 @@
+name "bindbc-lua"
+description "Static & dynamic bindings to Lua 5.1 and up, compatible with BetterC, @nogc, and nothrow."
+authors "Mike Parker"
+license "BSL-1.0"
+
+targetType "staticLibrary"
+targetPath "lib"
+targetName "BindBC_Lua"
+
+configuration "dynamic" {
+    dependency "bindbc-loader" version="~>1.1.0"
+    versions "BindLua_Dynamic"
+}
+
+configuration "dynamicBC" {
+    dependency "bindbc-loader" version="~>1.1.0"
+    subConfiguration "bindbc-loader" "yesBC"
+    buildOptions "betterC"
+    versions "BindLua_Dynamic"
+}
+
+configuration "static" {
+    versions "BindLua_Static"
+    excludedSourceFiles "source/bindbc/lua/v51/binddynamic.d" "source/bindbc/lua/v52/binddynamic.d" "source/bindbc/lua/v53/binddynamic.d"
+}
+
+configuration "staticBC" {
+    buildOptions "betterC"
+    versions "BindLua_Static"
+    excludedSourceFiles "source/bindbc/lua/v51/binddynamic.d" "source/bindbc/lua/v52/binddynamic.d" "source/bindbc/lua/v53/binddynamic.d"
+}

+ 29 - 0
source/bindbc/lua/config.d

@@ -0,0 +1,29 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua.config;
+
+enum LuaSupport {
+    noLibrary,
+    badLibrary,
+    lua51 = 51,
+    lua52 = 52,
+    lua53 = 53,
+    lua54 = 54,
+}
+
+version(LUA_54) {
+    enum luaSupport = LuaSupport.lua54;
+}
+else version(LUA_53) {
+    enum luaSupport = LuaSupport.lua53;
+}
+else version(LUA_52) {
+    enum luaSupport = LuaSupport.lua52;
+}
+else version(LUA_51) {
+    enum luaSupport = LuaSupport.lua51;
+}

+ 14 - 0
source/bindbc/lua/package.d

@@ -0,0 +1,14 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua;
+public import bindbc.lua.config;
+
+version(LUA_54) public import bindbc.lua.v54;
+else version(LUA_53) public import bindbc.lua.v53;
+else version(LUA_52) public import bindbc.lua.v52;
+else version(LUA_51) public import bindbc.lua.v51;
+else static assert(0, "Please specify a Lua version on the commandline (e.g. -version=LUA_52) or in your dub.json/sdl configuration");

+ 465 - 0
source/bindbc/lua/v51/binddynamic.d

@@ -0,0 +1,465 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua.v51.binddynamic;
+
+version(BindBC_Static) version = BindLua_Static;
+version(BindLua_Static) {}
+else version = BindLua_Dynamic;
+
+version(LUA_51) {
+    version(BindLua_Dynamic) version = LUA_51_DYNAMIC;
+}
+
+version(LUA_51_DYNAMIC):
+
+import core.stdc.stdarg : va_list;
+import bindbc.loader;
+import bindbc.lua.config;
+import bindbc.lua.v51.types;
+
+extern(C) @nogc nothrow {
+    // lauxlib.h
+    alias pluaI_openlib = void function(lua_State* L,const(char)* libname, const(luaL_Reg)* l, int nup);
+    alias pluaL_register = void function(lua_State* L, const(char)* libname, const(luaL_Reg)* l);
+    alias pluaL_getmetafield = int function(lua_State* L, int obj, const(char)* e);
+    alias pluaL_callmeta = int function(lua_State* L,  int obj, const(char)* e);
+    alias pluaL_typerror = int function(lua_State* L, int narg, const(char)* tname);
+    alias pluaL_argerror = int function(lua_State* L, int numarg, const(char)* extramsg);
+    alias pluaL_checklstring = const(char)* function(lua_State* L, int numarg, size_t* l);
+    alias pluaL_optlstring = const(char)* function(lua_State* L, int numArg, const(char)* def, size_t* l);
+    alias pluaL_checknumber = lua_Number function(lua_State* L, int numArg);
+    alias pluaL_optnumber = lua_Number function(lua_State* L, int nArg, lua_Number def);
+    alias pluaL_checkinteger = lua_Integer function(lua_State* L, int numArg);
+    alias pluaL_optinteger = lua_Integer function(lua_State* L, int nArg, lua_Integer def);
+    alias pluaL_checkstack = void function(lua_State* L, int sz, const(char)* msg);
+    alias pluaL_checktype = void function(lua_State* L, int narg, int t);
+    alias pluaL_checkany = void function(lua_State* L, int narg);
+    alias pluaL_newmetatable = int function(lua_State* L, const(char)* tname);
+    alias pluaL_checkudata = void* function(lua_State* L, int ud, const(char)* tname);
+    alias pluaL_where = void function(lua_State* L, int lvl);
+    alias pluaL_error = int function(lua_State* L, const(char)* fmt, ...);
+    alias pluaL_checkoption = int function(lua_State* L, int narg, const(char)* def, const(char)** lst);
+    alias pluaL_ref = int function(lua_State* L, int t);
+    alias pluaL_unref = void function(lua_State* L, int t, int ref_);
+    alias pluaL_loadfile = int function(lua_State* L, const(char)* filename);
+    alias pluaL_loadbuffer = int function(lua_State* L, const(char)* buff, size_t sz, const(char)* name);
+    alias pluaL_loadstring = int function(lua_State* L, const(char)* s);
+    alias pluaL_newstate = lua_State* function();
+    alias pluaL_gsub = const(char)* function(lua_State* L, const(char)* s, const(char)* p, const(char)* r);
+    alias pluaL_findtable = const(char)* function(lua_State* L, int idx, const(char)* fname, int szhint);
+    alias pluaL_buffinit = void function(lua_State* L, luaL_Buffer* B);
+    alias pluaL_prepbuffer = char* function(luaL_Buffer* B);
+    alias pluaL_addlstring = void function(luaL_Buffer* B, const(char)* s, size_t l);
+    alias pluaL_addstring = void function(luaL_Buffer* B,  const(char)* s);
+    alias pluaL_addvalue = void function(luaL_Buffer* B);
+    alias pluaL_pushresult = void function(luaL_Buffer* B);
+
+    // lua.h
+    alias plua_newstate = lua_State* function(lua_Alloc f,  void *ud);
+    alias plua_close = void function(lua_State* L);
+    alias plua_newthread = lua_State* function(lua_State* L);
+    alias plua_atpanic = lua_CFunction function(lua_State* L, lua_CFunction panicf);
+    alias plua_gettop = int function(lua_State* L);
+    alias plua_settop = void function(lua_State* L, int idx);
+    alias plua_pushvalue = void function(lua_State* L, int idx);
+    alias plua_remove = void function(lua_State* L, int idx);
+    alias plua_insert = void function(lua_State* L, int idx);
+    alias plua_replace = void function(lua_State* L, int idx);
+    alias plua_checkstack = int function(lua_State* L, int idx);
+    alias plua_xmove = void function(lua_State* L, lua_State*, int idx);
+    alias plua_isnumber = int function(lua_State* L, int idx);
+    alias plua_isstring = int function(lua_State* L, int idx);
+    alias plua_iscfunction = int function(lua_State* L, int idx);
+    alias plua_isuserdata = int function(lua_State* L, int idx);
+    alias plua_type = int function(lua_State* L, int idx);
+    alias plua_typename = const(char)* function(lua_State* L, int tp);
+    alias plua_equal = int function(lua_State* L, int idx1, int idx2);
+    alias plua_rawequal = int function(lua_State* L, int idx1, int idx2);
+    alias plua_lessthan = int function(lua_State* L, int idx1, int idx2);
+    alias plua_tonumber = lua_Number function(lua_State* L, int idx);
+    alias plua_tointeger = lua_Integer function(lua_State* L, int idx);
+    alias plua_toboolean = int function(lua_State* L, int idx);
+    alias plua_tolstring = const(char)* function(lua_State* L, int idx, size_t* len);
+    alias plua_objlen = size_t function(lua_State* L, int idx);
+    alias plua_tocfunction = lua_CFunction function(lua_State* L, int idx);
+    alias plua_touserdata = void* function(lua_State* L, int idx);
+    alias plua_tothread = lua_State* function(lua_State* L, int idx);
+    alias plua_topointer = const(void)* function(lua_State* L, int idx);
+    alias plua_pushnil = void function(lua_State* L);
+    alias plua_pushnumber = void function(lua_State* L, lua_Number n);
+    alias plua_pushinteger = void function(lua_State* L, lua_Integer n);
+    alias plua_pushlstring = void function(lua_State* L, const(char)* s, size_t l);
+    alias plua_pushstring = void function(lua_State* L, const(char)* s);
+    alias plua_pushvfstring = const(char)* function(lua_State* L, const(char)* fmt, va_list argp);
+    alias plua_pushfstring = const(char)* function(lua_State* L, const(char)* fmt, ...);
+    alias plua_pushcclosure = void function(lua_State* L, lua_CFunction fn, int n);
+    alias plua_pushboolean = void function(lua_State* L, int b);
+    alias plua_pushlightuserdata = void function(lua_State* L, void* p);
+    alias plua_pushthread = int function(lua_State* L);
+    alias plua_gettable = void function(lua_State* L, int idx);
+    alias plua_getfield = void function(lua_State* L, int idx, const(char)* k);
+    alias plua_rawget = void function(lua_State* L, int idx);
+    alias plua_rawgeti = void function(lua_State* L, int idx, int n);
+    alias plua_createtable = void function(lua_State* L, int narr, int nrec);
+    alias plua_newuserdata = void* function(lua_State* L, size_t sz);
+    alias plua_getmetatable = int function(lua_State* L, int objindex);
+    alias plua_getfenv = void function(lua_State* L, int idx);
+    alias plua_settable = void function(lua_State* L, int idx);
+    alias plua_setfield = void function(lua_State* L, int idx, const(char)* k);
+    alias plua_rawset = void function(lua_State* L, int idx);
+    alias plua_rawseti = void function(lua_State* L, int idx, int n);
+    alias plua_setmetatable = int function(lua_State* L, int objindex);
+    alias plua_setfenv = int function(lua_State* L, int idx);
+    alias plua_call = void function(lua_State* L, int nargs, int nresults);
+    alias plua_pcall = int function(lua_State* L, int nargs, int nresults, int errFunc);
+    alias plua_cpcall = int function(lua_State* L, lua_CFunction func, void* ud);
+    alias plua_load = int function(lua_State* L, lua_Reader reader, void* dt, const(char)* chunkname);
+    alias plua_dump = int function(lua_State* L, lua_Writer writer, void* data);
+    alias plua_yield = int function(lua_State* L, int nresults);
+    alias plua_resume = int function(lua_State* L, int nargs);
+    alias plua_status = int function(lua_State* L);
+    alias plua_gc = int function(lua_State* L, int what, int data);
+    alias plua_error = int function(lua_State* L);
+    alias plua_next = int function(lua_State* L, int idx);
+    alias plua_concat = void function(lua_State* L, int n);
+    alias plua_getallocf = lua_Alloc function(lua_State* L, void** ud);
+    alias plua_setallocf = void function(lua_State* L, lua_Alloc f, void* ud);
+    alias plua_setlevel = void function(lua_State* from,  lua_State* to);
+    alias plua_getstack = int function(lua_State* L, int level, lua_Debug* ar);
+    alias plua_getinfo = int function(lua_State* L, const(char)* what, lua_Debug* ar);
+    alias plua_getlocal = const(char)* function(lua_State* L, const(lua_Debug)* ar, int n);
+    alias plua_setlocal = const(char)* function(lua_State* L, const(lua_Debug)* ar, int n);
+    alias plua_getupvalue = const(char)* function(lua_State* L, int funcindex, int n);
+    alias plua_setupvalue = const(char)* function(lua_State* L, int funcindex, int n);
+    alias plua_sethook = int function(lua_State* L, lua_Hook func, int mask, int count);
+    alias plua_gethook = lua_Hook function(lua_State* L);
+    alias plua_gethookmask = int function(lua_State* L);
+    alias plua_gethookcount = int function(lua_State* L);
+
+    // lualib.h
+    alias pluaopen_base = int function(lua_State* L);
+    alias pluaopen_table = int function(lua_State* L);
+    alias pluaopen_io = int function(lua_State* L);
+    alias pluaopen_os = int function(lua_State* L);
+    alias pluaopen_string = int function(lua_State* L);
+    alias pluaopen_math = int function(lua_State* L);
+    alias pluaopen_debug = int function(lua_State* L);
+    alias pluaopen_package = int function(lua_State* L);
+    alias pluaL_openlibs = void function(lua_State* L);
+}
+
+__gshared {
+    // lauxlib.h
+    pluaI_openlib luaI_openlib;
+    pluaL_register luaL_register;
+    pluaL_getmetafield luaL_getmetafield;
+    pluaL_callmeta luaL_callmeta;
+    pluaL_typerror luaL_typerror;
+    pluaL_argerror luaL_argerror;
+    pluaL_checklstring luaL_checklstring;
+    pluaL_optlstring luaL_optlstring;
+    pluaL_checknumber luaL_checknumber;
+    pluaL_optnumber luaL_optnumber;
+    pluaL_checkinteger luaL_checkinteger;
+    pluaL_optinteger luaL_optinteger;
+    pluaL_checkstack luaL_checkstack;
+    pluaL_checktype luaL_checktype;
+    pluaL_checkany luaL_checkany;
+    pluaL_newmetatable luaL_newmetatable;
+    pluaL_checkudata luaL_checkudata;
+    pluaL_where luaL_where;
+    pluaL_error luaL_error;
+    pluaL_checkoption luaL_checkoption;
+    pluaL_ref luaL_ref;
+    pluaL_unref luaL_unref;
+    pluaL_loadfile luaL_loadfile;
+    pluaL_loadbuffer luaL_loadbuffer;
+    pluaL_loadstring luaL_loadstring;
+    pluaL_newstate luaL_newstate;
+    pluaL_gsub luaL_gsub;
+    pluaL_findtable luaL_findtable;
+    pluaL_buffinit luaL_buffinit;
+    pluaL_prepbuffer luaL_prepbuffer;
+    pluaL_addlstring luaL_addlstring;
+    pluaL_addstring luaL_addstring;
+    pluaL_addvalue luaL_addvalue;
+    pluaL_pushresult luaL_pushresult;
+
+    // lua.h
+    plua_newstate lua_newstate;
+    plua_close lua_close;
+    plua_newthread lua_newthread;
+    plua_atpanic lua_atpanic;
+    plua_gettop lua_gettop;
+    plua_settop lua_settop;
+    plua_pushvalue lua_pushvalue;
+    plua_remove lua_remove;
+    plua_insert lua_insert;
+    plua_replace lua_replace;
+    plua_checkstack lua_checkstack;
+    plua_xmove lua_xmove;
+    plua_isnumber lua_isnumber;
+    plua_isstring lua_isstring;
+    plua_iscfunction lua_iscfunction;
+    plua_isuserdata lua_isuserdata;
+    plua_type lua_type;
+    plua_typename lua_typename;
+    plua_equal lua_equal;
+    plua_rawequal lua_rawequal;
+    plua_lessthan lua_lessthan;
+    plua_tonumber lua_tonumber;
+    plua_tointeger lua_tointeger;
+    plua_toboolean lua_toboolean;
+    plua_tolstring lua_tolstring;
+    plua_objlen lua_objlen;
+    plua_tocfunction lua_tocfunction;
+    plua_touserdata lua_touserdata;
+    plua_tothread lua_tothread;
+    plua_topointer lua_topointer;
+    plua_pushnil lua_pushnil;
+    plua_pushnumber lua_pushnumber;
+    plua_pushinteger lua_pushinteger;
+    plua_pushlstring lua_pushlstring;
+    plua_pushstring lua_pushstring;
+    plua_pushvfstring lua_pushvfstring;
+    plua_pushfstring lua_pushfstring;
+    plua_pushcclosure lua_pushcclosure;
+    plua_pushboolean lua_pushboolean;
+    plua_pushlightuserdata lua_pushlightuserdata;
+    plua_pushthread lua_pushthread;
+    plua_gettable lua_gettable;
+    plua_getfield lua_getfield;
+    plua_rawget lua_rawget;
+    plua_rawgeti lua_rawgeti;
+    plua_createtable lua_createtable;
+    plua_newuserdata lua_newuserdata;
+    plua_getmetatable lua_getmetatable;
+    plua_getfenv lua_getfenv;
+    plua_settable lua_settable;
+    plua_setfield lua_setfield;
+    plua_rawset lua_rawset;
+    plua_rawseti lua_rawseti;
+    plua_setmetatable lua_setmetatable;
+    plua_setfenv lua_setfenv;
+    plua_call lua_call;
+    plua_pcall lua_pcall;
+    plua_cpcall lua_cpcall;
+    plua_load lua_load;
+    plua_dump lua_dump;
+    plua_yield lua_yield;
+    plua_resume lua_resume;
+    plua_status lua_status;
+    plua_gc lua_gc;
+    plua_error lua_error;
+    plua_next lua_next;
+    plua_concat lua_concat;
+    plua_getallocf lua_getallocf;
+    plua_setallocf lua_setallocf;
+    plua_setlevel lua_setlevel;
+    plua_getstack lua_getstack;
+    plua_getinfo lua_getinfo;
+    plua_getlocal lua_getlocal;
+    plua_setlocal lua_setlocal;
+    plua_getupvalue lua_getupvalue;
+    plua_setupvalue lua_setupvalue;
+    plua_sethook lua_sethook;
+    plua_gethook lua_gethook;
+    plua_gethookmask lua_gethookmask;
+    plua_gethookcount lua_gethookcount;
+
+    // lualib.h
+    pluaopen_base luaopen_base;
+    pluaopen_table luaopen_table;
+    pluaopen_io luaopen_io;
+    pluaopen_os luaopen_os;
+    pluaopen_string luaopen_string;
+    pluaopen_math luaopen_math;
+    pluaopen_debug luaopen_debug;
+    pluaopen_package luaopen_package;
+    pluaL_openlibs luaL_openlibs;
+}
+
+private {
+    SharedLib lib;
+    LuaSupport loadedVersion;
+}
+
+@nogc nothrow:
+
+void unloadLua()
+{
+    if(lib != invalidHandle) {
+        lib.unload;
+    }
+}
+
+LuaSupport loadedLuaVersion() @safe { return loadedVersion; }
+bool isLuaLoaded() @safe { return lib != invalidHandle; }
+
+LuaSupport loadLua()
+{
+    version(Windows) {
+        const(char)[][3] libNames = ["lua5.1.dll", "lua51.dll", "lua5.1.5.dll"];
+    }
+    else version(OSX) {
+        const(char)[][1] libNames = "liblua.5.1.dylib";
+    }
+    else version(Posix) {
+        const(char)[][3] libNames = ["liblua.so.5.1", "liblua5.1.so", "liblua-5.1.so"];
+    }
+    else static assert(0, "bindbc-lua support for Lua 5.1 is not implemented on this platform.");
+
+    LuaSupport ret;
+    foreach(name; libNames) {
+        ret = loadLua(name.ptr);
+        if(ret != LuaSupport.noLibrary) break;
+    }
+    return ret;
+}
+
+LuaSupport loadLua(const(char)* libName)
+{
+    lib = load(libName);
+    if(lib == invalidHandle) {
+        return LuaSupport.noLibrary;
+    }
+
+    auto errCount = errorCount();
+    loadedVersion = LuaSupport.badLibrary;
+
+    // lauxlib.h
+    lib.bindSymbol(cast(void**)&luaI_openlib, "luaI_openlib");
+    lib.bindSymbol(cast(void**)&luaL_register, "luaL_register");
+    lib.bindSymbol(cast(void**)&luaL_getmetafield,"luaL_getmetafield");
+    lib.bindSymbol(cast(void**)&luaL_callmeta, "luaL_callmeta");
+    lib.bindSymbol(cast(void**)&luaL_typerror, "luaL_typerror");
+    lib.bindSymbol(cast(void**)&luaL_checklstring, "luaL_checklstring");
+    lib.bindSymbol(cast(void**)&luaL_argerror, "luaL_argerror");
+    lib.bindSymbol(cast(void**)&luaL_optlstring, "luaL_optlstring");
+    lib.bindSymbol(cast(void**)&luaL_checknumber, "luaL_checknumber");
+    lib.bindSymbol(cast(void**)&luaL_optnumber, "luaL_optnumber");
+    lib.bindSymbol(cast(void**)&luaL_checkinteger, "luaL_checkinteger");
+    lib.bindSymbol(cast(void**)&luaL_optinteger, "luaL_optinteger");
+    lib.bindSymbol(cast(void**)&luaL_checkstack, "luaL_checkstack");
+    lib.bindSymbol(cast(void**)&luaL_checktype, "luaL_checktype");
+    lib.bindSymbol(cast(void**)&luaL_checkany, "luaL_checkany");
+    lib.bindSymbol(cast(void**)&luaL_newmetatable, "luaL_newmetatable");
+    lib.bindSymbol(cast(void**)&luaL_checkudata, "luaL_checkudata");
+    lib.bindSymbol(cast(void**)&luaL_where, "luaL_where");
+    lib.bindSymbol(cast(void**)&luaL_error, "luaL_error");
+    lib.bindSymbol(cast(void**)&luaL_checkoption, "luaL_checkoption");
+    lib.bindSymbol(cast(void**)&luaL_ref, "luaL_ref");
+    lib.bindSymbol(cast(void**)&luaL_unref, "luaL_unref");
+    lib.bindSymbol(cast(void**)&luaL_loadfile, "luaL_loadfile");
+    lib.bindSymbol(cast(void**)&luaL_loadbuffer, "luaL_loadbuffer");
+    lib.bindSymbol(cast(void**)&luaL_loadstring, "luaL_loadstring");
+    lib.bindSymbol(cast(void**)&luaL_newstate, "luaL_newstate");
+    lib.bindSymbol(cast(void**)&luaL_gsub, "luaL_gsub");
+    lib.bindSymbol(cast(void**)&luaL_findtable, "luaL_findtable");
+
+    lib.bindSymbol(cast(void**)&luaL_buffinit, "luaL_buffinit");
+    lib.bindSymbol(cast(void**)&luaL_prepbuffer, "luaL_prepbuffer");
+    lib.bindSymbol(cast(void**)&luaL_addlstring, "luaL_addlstring");
+    lib.bindSymbol(cast(void**)&luaL_addstring, "luaL_addstring");
+    lib.bindSymbol(cast(void**)&luaL_addvalue, "luaL_addvalue");
+    lib.bindSymbol(cast(void**)&luaL_pushresult, "luaL_pushresult");
+
+    // lua.h
+    lib.bindSymbol(cast(void**)&lua_newstate, "lua_newstate");
+    lib.bindSymbol(cast(void**)&lua_close, "lua_close");
+    lib.bindSymbol(cast(void**)&lua_newthread, "lua_newthread");
+    lib.bindSymbol(cast(void**)&lua_atpanic, "lua_atpanic");
+    lib.bindSymbol(cast(void**)&lua_gettop, "lua_gettop");
+    lib.bindSymbol(cast(void**)&lua_settop, "lua_settop");
+    lib.bindSymbol(cast(void**)&lua_pushvalue, "lua_pushvalue");
+    lib.bindSymbol(cast(void**)&lua_remove, "lua_remove");
+    lib.bindSymbol(cast(void**)&lua_insert, "lua_insert");
+    lib.bindSymbol(cast(void**)&lua_replace, "lua_replace");
+    lib.bindSymbol(cast(void**)&lua_checkstack, "lua_checkstack");
+    lib.bindSymbol(cast(void**)&lua_xmove, "lua_xmove");
+    lib.bindSymbol(cast(void**)&lua_isnumber, "lua_isnumber");
+    lib.bindSymbol(cast(void**)&lua_isstring, "lua_isstring");
+    lib.bindSymbol(cast(void**)&lua_iscfunction, "lua_iscfunction");
+    lib.bindSymbol(cast(void**)&lua_isuserdata, "lua_isuserdata");
+    lib.bindSymbol(cast(void**)&lua_type, "lua_type");
+    lib.bindSymbol(cast(void**)&lua_typename, "lua_typename");
+    lib.bindSymbol(cast(void**)&lua_equal, "lua_equal");
+    lib.bindSymbol(cast(void**)&lua_rawequal, "lua_rawequal");
+    lib.bindSymbol(cast(void**)&lua_lessthan, "lua_lessthan");
+    lib.bindSymbol(cast(void**)&lua_tonumber, "lua_tonumber");
+    lib.bindSymbol(cast(void**)&lua_tointeger, "lua_tointeger");
+    lib.bindSymbol(cast(void**)&lua_toboolean, "lua_toboolean");
+    lib.bindSymbol(cast(void**)&lua_tolstring, "lua_tolstring");
+    lib.bindSymbol(cast(void**)&lua_objlen, "lua_objlen");
+    lib.bindSymbol(cast(void**)&lua_tocfunction, "lua_tocfunction");
+    lib.bindSymbol(cast(void**)&lua_touserdata, "lua_touserdata");
+    lib.bindSymbol(cast(void**)&lua_tothread, "lua_tothread");
+    lib.bindSymbol(cast(void**)&lua_topointer, "lua_topointer");
+    lib.bindSymbol(cast(void**)&lua_pushnil, "lua_pushnil");
+    lib.bindSymbol(cast(void**)&lua_pushnumber, "lua_pushnumber");
+    lib.bindSymbol(cast(void**)&lua_pushinteger, "lua_pushinteger");
+    lib.bindSymbol(cast(void**)&lua_pushlstring, "lua_pushlstring");
+    lib.bindSymbol(cast(void**)&lua_pushstring, "lua_pushstring");
+    lib.bindSymbol(cast(void**)&lua_pushvfstring, "lua_pushvfstring");
+    lib.bindSymbol(cast(void**)&lua_pushfstring, "lua_pushfstring");
+    lib.bindSymbol(cast(void**)&lua_pushcclosure, "lua_pushcclosure");
+    lib.bindSymbol(cast(void**)&lua_pushboolean, "lua_pushboolean");
+    lib.bindSymbol(cast(void**)&lua_pushlightuserdata, "lua_pushlightuserdata");
+    lib.bindSymbol(cast(void**)&lua_pushthread, "lua_pushthread");
+    lib.bindSymbol(cast(void**)&lua_gettable, "lua_gettable");
+    lib.bindSymbol(cast(void**)&lua_getfield, "lua_getfield");
+    lib.bindSymbol(cast(void**)&lua_rawget, "lua_rawget");
+    lib.bindSymbol(cast(void**)&lua_rawgeti, "lua_rawgeti");
+    lib.bindSymbol(cast(void**)&lua_createtable, "lua_createtable");
+    lib.bindSymbol(cast(void**)&lua_newuserdata, "lua_newuserdata");
+    lib.bindSymbol(cast(void**)&lua_getmetatable, "lua_getmetatable");
+    lib.bindSymbol(cast(void**)&lua_getfenv, "lua_getfenv");
+    lib.bindSymbol(cast(void**)&lua_settable, "lua_settable");
+    lib.bindSymbol(cast(void**)&lua_setfield, "lua_setfield");
+    lib.bindSymbol(cast(void**)&lua_rawset, "lua_rawset");
+    lib.bindSymbol(cast(void**)&lua_rawseti, "lua_rawseti");
+    lib.bindSymbol(cast(void**)&lua_setmetatable, "lua_setmetatable");
+    lib.bindSymbol(cast(void**)&lua_setfenv, "lua_setfenv");
+    lib.bindSymbol(cast(void**)&lua_call, "lua_call");
+    lib.bindSymbol(cast(void**)&lua_pcall, "lua_pcall");
+    lib.bindSymbol(cast(void**)&lua_cpcall, "lua_cpcall");
+    lib.bindSymbol(cast(void**)&lua_load, "lua_load");
+    lib.bindSymbol(cast(void**)&lua_dump, "lua_dump");
+    lib.bindSymbol(cast(void**)&lua_yield, "lua_yield");
+    lib.bindSymbol(cast(void**)&lua_resume, "lua_resume");
+    lib.bindSymbol(cast(void**)&lua_status, "lua_status");
+    lib.bindSymbol(cast(void**)&lua_gc, "lua_gc");
+    lib.bindSymbol(cast(void**)&lua_error, "lua_error");
+    lib.bindSymbol(cast(void**)&lua_next, "lua_next");
+    lib.bindSymbol(cast(void**)&lua_concat, "lua_concat");
+    lib.bindSymbol(cast(void**)&lua_getallocf, "lua_getallocf");
+    lib.bindSymbol(cast(void**)&lua_setallocf, "lua_setallocf");
+    lib.bindSymbol(cast(void**)&lua_setlevel, "lua_setlevel");
+    lib.bindSymbol(cast(void**)&lua_getstack, "lua_getstack");
+    lib.bindSymbol(cast(void**)&lua_getinfo, "lua_getinfo");
+    lib.bindSymbol(cast(void**)&lua_getlocal, "lua_getlocal");
+    lib.bindSymbol(cast(void**)&lua_setlocal, "lua_setlocal");
+    lib.bindSymbol(cast(void**)&lua_getupvalue, "lua_getupvalue");
+    lib.bindSymbol(cast(void**)&lua_setupvalue, "lua_setupvalue");
+    lib.bindSymbol(cast(void**)&lua_sethook, "lua_sethook");
+    lib.bindSymbol(cast(void**)&lua_gethook, "lua_gethook");
+    lib.bindSymbol(cast(void**)&lua_gethookmask, "lua_gethookmask");
+    lib.bindSymbol(cast(void**)&lua_gethookcount, "lua_gethookcount");
+
+    // lualib.h
+    lib.bindSymbol(cast(void**)&luaopen_base, "luaopen_base");
+    lib.bindSymbol(cast(void**)&luaopen_table, "luaopen_table");
+    lib.bindSymbol(cast(void**)&luaopen_io, "luaopen_io");
+    lib.bindSymbol(cast(void**)&luaopen_os, "luaopen_os");
+    lib.bindSymbol(cast(void**)&luaopen_string, "luaopen_string");
+    lib.bindSymbol(cast(void**)&luaopen_math, "luaopen_math");
+    lib.bindSymbol(cast(void**)&luaopen_debug, "luaopen_debug");
+    lib.bindSymbol(cast(void**)&luaopen_package, "luaopen_package");
+    lib.bindSymbol(cast(void**)&luaL_openlibs, "luaL_openlibs");
+
+    return LuaSupport.lua51;
+}

+ 147 - 0
source/bindbc/lua/v51/bindstatic.d

@@ -0,0 +1,147 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua.v51.bindstatic;
+
+version(BindBC_Static) version = BindLua_Static;
+version(BindLua_Static) {
+    version(LUA_51) version = LUA_51_STATIC;
+}
+
+version(LUA_51_STATIC):
+
+import core.stdc.stdarg : va_list;
+import bindbc.lua.v51.types;
+
+extern(C) @nogc nothrow:
+    // lauxlib.h
+    void luaI_openlib(lua_State* L, const(char)* libname, const(luaL_Reg)* l, int nup);
+    void luaL_register(lua_State* L, const(char)* libname, const(luaL_Reg)* l);
+    int luaL_getmetafield(lua_State* L, int obj, const(char)* e);
+    int luaL_callmeta(lua_State* L,  int obj, const(char)* e);
+    int luaL_typerror(lua_State* L, int narg, const(char)* tname);
+    int luaL_argerror(lua_State* L, int numarg, const(char)* extramsg);
+    const(char)* luaL_checklstring(lua_State* L, int numarg, size_t* l);
+    const(char)* luaL_optlstring(lua_State* L, int numArg, const(char)* def, size_t* l);
+    lua_Number luaL_checknumber(lua_State* L, int numArg);
+    lua_Number luaL_optnumber(lua_State* L, int nArg, lua_Number def);
+    lua_Integer luaL_checkinteger(lua_State* L, int numArg);
+    lua_Integer luaL_optinteger(lua_State* L, int nArg, lua_Integer def);
+    void luaL_checkstack(lua_State* L, int sz, const(char)* msg);
+    void luaL_checktype(lua_State* L, int narg, int t);
+    void luaL_checkany(lua_State* L, int narg);
+    int luaL_newmetatable(lua_State* L, const(char)* tname);
+    void* luaL_checkudata(lua_State* L, int ud, const(char)* tname);
+    void luaL_where(lua_State* L, int lvl);
+    int luaL_error(lua_State* L, const(char)* fmt, ...);
+    int luaL_checkoption(lua_State* L, int narg, const(char)* def, const(char)** lst);
+    int luaL_ref(lua_State* L, int t);
+    void luaL_unref(lua_State* L, int t, int ref_);
+    int luaL_loadfile(lua_State* L, const(char)* filename);
+    int luaL_loadbuffer(lua_State* L, const(char)* buff, size_t sz, const(char)* name);
+    int luaL_loadstring(lua_State* L, const(char)* s);
+    lua_State* luaL_newstate();
+    const(char)* luaL_gsub(lua_State* L, const(char)* s, const(char)* p, const(char)* r);
+    const(char)* luaL_findtable(lua_State* L, int idx, const(char)* fname, int szhint);
+    void luaL_buffinit(lua_State* L, luaL_Buffer* B);
+    char* luaL_prepbuffer(luaL_Buffer* B);
+    void luaL_addlstring(luaL_Buffer* B, const(char)* s, size_t l);
+    void luaL_addstring(luaL_Buffer* B,  const(char)* s);
+    void luaL_addvalue(luaL_Buffer* B);
+    void luaL_pushresult(luaL_Buffer* B);
+
+    // lua.h
+    lua_State* lua_newstate(lua_Alloc f,  void *ud);
+    lua_State* lua_close(lua_State* L);
+    lua_State* lua_newthread(lua_State* L);
+    lua_CFunction lua_atpanic(lua_State* L, lua_CFunction panicf);
+    int lua_gettop(lua_State* L);
+    void lua_settop(lua_State* L, int idx);
+    void lua_pushvalue(lua_State* L, int idx);
+    void lua_remove(lua_State* L, int idx);
+    void lua_insert(lua_State* L, int idx);
+    void lua_replace(lua_State* L, int idx);
+    int lua_checkstack(lua_State* L, int idx);
+    void lua_xmove(lua_State* L, lua_State*, int idx);
+    int lua_isnumber(lua_State* L, int idx);
+    int lua_isstring(lua_State* L, int idx);
+    int lua_iscfunction(lua_State* L, int idx);
+    int lua_isuserdata(lua_State* L, int idx);
+    int lua_type(lua_State* L, int idx);
+    const(char)* lua_typename(lua_State* L, int tp);
+    int lua_equal(lua_State* L, int idx1, int idx2);
+    int lua_rawequal(lua_State* L, int idx1, int idx2);
+    int lua_lessthan(lua_State* L, int idx1, int idx2);
+    lua_Number lua_tonumber(lua_State* L, int idx);
+    lua_Integer lua_tointeger(lua_State* L, int idx);
+    int lua_toboolean(lua_State* L, int idx);
+    const(char)* lua_tolstring(lua_State* L, int idx, size_t* len);
+    size_t lua_objlen(lua_State* L, int idx);
+    lua_CFunction lua_tocfunction(lua_State* L, int idx);
+    void* lua_touserdata(lua_State* L, int idx);
+    lua_State* lua_tothread(lua_State* L, int idx);
+    const(void)* lua_topointer(lua_State* L, int idx);
+    void lua_pushnil(lua_State* L);
+    void lua_pushnumber(lua_State* L, lua_Number n);
+    void lua_pushinteger(lua_State* L, lua_Integer n);
+    void lua_pushlstring(lua_State* L, const(char)* s, size_t l);
+    void lua_pushstring(lua_State* L, const(char)* s);
+    const(char)* lua_pushvfstring(lua_State* L, const(char)* fmt, va_list argp);
+    const(char)* lua_pushfstring(lua_State* L, const(char)* fmt, ...);
+    void lua_pushcclosure(lua_State* L, lua_CFunction fn, int n);
+    void lua_pushboolean(lua_State* L, int b);
+    void lua_pushlightuserdata(lua_State* L, void* p);
+    int lua_pushthread(lua_State* L);
+    void lua_gettable(lua_State* L, int idx);
+    void lua_getfield(lua_State* L, int idx, const(char)* k);
+    void lua_rawget(lua_State* L, int idx);
+    void lua_rawgeti(lua_State* L, int idx, int n);
+    void lua_createtable(lua_State* L, int narr, int nrec);
+    void* lua_newuserdata(lua_State* L, size_t sz);
+    int lua_getmetatable(lua_State* L, int objindex);
+    void lua_getfenv(lua_State* L, int idx);
+    void lua_settable(lua_State* L, int idx);
+    void lua_setfield(lua_State* L, int idx, const(char)* k);
+    void lua_rawset(lua_State* L, int idx);
+    void lua_rawseti(lua_State* L, int idx, int n);
+    int lua_setmetatable(lua_State* L, int objindex);
+    int lua_setfenv(lua_State* L, int idx);
+    void lua_call(lua_State* L, int nargs, int nresults);
+    int lua_pcall(lua_State* L, int nargs, int nresults, int errFunc);
+    int lua_cpcall(lua_State* L, lua_CFunction func, void* ud);
+    int lua_load(lua_State* L, lua_Reader reader, void* dt, const(char)* chunkname);
+    int lua_dump(lua_State* L, lua_Writer writer, void* data);
+    int lua_yield(lua_State* L, int nresults);
+    int lua_resume(lua_State* L, int nargs);
+    int lua_status(lua_State* L);
+    int lua_gc(lua_State* L, int what, int data);
+    int lua_error(lua_State* L);
+    int lua_next(lua_State* L, int idx);
+    void lua_concat(lua_State* L, int n);
+    lua_Alloc lua_getallocf(lua_State* L, void** ud);
+    void lua_setallocf(lua_State* L, lua_Alloc f, void* ud);
+    void lua_setlevel(lua_State* from,  lua_State* to);
+    int lua_getstack(lua_State* L, int level, lua_Debug* ar);
+    int lua_getinfo(lua_State* L, const(char)* what, lua_Debug* ar);
+    const(char)* lua_getlocal(lua_State* L, const(lua_Debug)* ar, int n);
+    const(char)* lua_setlocal(lua_State* L, const(lua_Debug)* ar, int n);
+    const(char)* lua_getupvalue(lua_State* L, int funcindex, int n);
+    const(char)* lua_setupvalue(lua_State* L, int funcindex, int n);
+    int lua_sethook(lua_State* L, lua_Hook func, int mask, int count);
+    lua_Hook lua_gethook(lua_State* L);
+    int lua_gethookmask(lua_State* L);
+    int lua_gethookcount(lua_State* L);
+
+    // lualib.h
+    int luaopen_base(lua_State* L);
+    int luaopen_table(lua_State* L);
+    int luaopen_io(lua_State* L);
+    int luaopen_os(lua_State* L);
+    int luaopen_string(lua_State* L);
+    int luaopen_math(lua_State* L);
+    int luaopen_debug(lua_State* L);
+    int luaopen_package(lua_State* L);
+    void luaL_openlibs(lua_State* L);

+ 194 - 0
source/bindbc/lua/v51/package.d

@@ -0,0 +1,194 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua.v51;
+
+version(LUA_51):
+
+public import bindbc.lua.v51.types;
+
+version(BindBC_Static) version = BindLua_Static;
+version(BindLua_Static) {
+    public import bindbc.lua.v51.bindstatic;
+}
+else public import bindbc.lua.v51.binddynamic;
+
+import core.stdc.config : c_long;
+
+// compatibility function aliases
+// lua.h
+alias lua_strlen = lua_objlen;
+alias lua_open = lua_newstate;
+
+// Macros
+@nogc nothrow {
+    // lauxlib.h
+    void luaL_argcheck(lua_State* L, bool cond, int arg, const(char)* extramsg) {
+        pragma(inline, true)
+        if(!cond) luaL_argerror(L, arg, extramsg);
+    }
+
+    const(char)* luaL_checkstring(lua_State* L, int arg) {
+        pragma(inline, true)
+        return luaL_checklstring(L, arg, null);
+    }
+
+    const(char)* luaL_optstring(lua_State* L, int arg, const(char)* d) {
+        pragma(inline, true)
+        return luaL_optlstring(L, arg, d, null);
+    }
+
+    int luaL_checkint(lua_State* L, int arg) {
+        pragma(inline, true)
+        return cast(int)luaL_checkinteger(L, arg);
+    }
+
+    int luaL_optint(lua_State* L, int arg, int d) {
+        pragma(inline, true)
+        return cast(int)luaL_optinteger(L, arg, d);
+    }
+
+    c_long luaL_checklong(lua_State* L, int arg) {
+        pragma(inline, true)
+        return cast(c_long)luaL_checkinteger(L, arg);
+    }
+
+    c_long luaL_optlong(lua_State* L, int arg, int d) {
+        pragma(inline, true)
+        return cast(c_long)luaL_optinteger(L, arg, d);
+    }
+
+    const(char)* luaL_typename(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_typename(L, lua_type(L, i));
+    }
+
+    bool luaL_dofile(lua_State* L, const(char)* filename) {
+        pragma(inline, true)
+        return luaL_loadfile(L, filename) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0;
+    }
+
+    bool luaL_dostring(lua_State* L, const(char)* str) {
+        pragma(inline, true)
+        return luaL_loadstring(L, str) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0;
+    }
+
+    void luaL_getmetatable(lua_State* L, const(char)* tname) {
+        pragma(inline, true)
+        lua_getfield(L, LUA_REGISTRYINDEX, tname);
+    }
+
+    // TODO: figure out what luaL_opt is supposed to do
+
+    void luaL_addchar(luaL_Buffer* B, char c) {
+        pragma(inline, true)
+        if(B.p < (B.buffer.ptr + LUAL_BUFFERSIZE) || luaL_prepbuffer(B)) {
+            *B.p++ = c;
+        }
+    }
+
+    void luaL_addsize(luaL_Buffer* B, size_t n) {
+        pragma(inline, true)
+        B.p += n;
+    }
+
+    // lua.h
+    int lua_upvalueindex(int i) {
+        pragma(inline, true)
+        return LUA_GLOBALSINDEX - i;
+    }
+
+    void lua_pop(lua_State* L, int n) {
+        pragma(inline, true)
+        lua_settop(L, -n - 1);
+    }
+
+    void lua_newtable(lua_State* L) {
+        pragma(inline, true)
+        lua_createtable(L, 0, 0);
+    }
+
+    void lua_register(lua_State* L, const(char)* n, lua_CFunction f) {
+        pragma(inline, true)
+        lua_pushcfunction(L, f);
+        lua_setglobal(L, n);
+    }
+
+    void lua_pushcfunction(lua_State* L, lua_CFunction f) {
+        pragma(inline, true)
+        lua_pushcclosure(L, f, 0);
+    }
+
+    bool lua_isfunction(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TFUNCTION;
+    }
+
+    bool lua_istable(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TTABLE;
+    }
+
+    bool lua_islightuserdata(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TLIGHTUSERDATA;
+    }
+
+    bool lua_isnil(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TNIL;
+    }
+
+    bool lua_isboolean(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TBOOLEAN;
+    }
+
+    bool lua_isthread(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TTHREAD;
+    }
+
+    bool lua_isnone(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TNONE;
+    }
+
+    bool lua_isnoneornil(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) <= 0;
+    }
+
+    void lua_pushliteral(lua_State* L, const(char)[] s) {
+        pragma(inline, true)
+        lua_pushlstring(L, s.ptr, s.length);
+    }
+
+    void lua_setglobal(lua_State* L, const(char)* s) {
+        pragma(inline, true)
+        lua_setfield(L, LUA_GLOBALSINDEX, s);
+    }
+
+    void lua_getglobal(lua_State* L, const(char)* s) {
+        pragma(inline, true)
+        lua_getfield(L, LUA_GLOBALSINDEX, s);
+    }
+
+    const(char)* lua_tostring(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_tolstring(L, i, null);
+    }
+
+    void lua_getregistry(lua_State* L) {
+        pragma(inline, true)
+        lua_pushvalue(L, LUA_REGISTRYINDEX);
+    }
+
+    int lua_getgccount(lua_State* L) {
+        pragma(inline, true)
+        return lua_gc(L, LUA_GCCOUNT, 0);
+    }
+}

+ 140 - 0
source/bindbc/lua/v51/types.d

@@ -0,0 +1,140 @@
+/+
++                Copyright 2023 Aya Partridge
++          Copyright 2019 - 2021 Michael D. Parker
++ Distributed under the Boost Software License, Version 1.0.
++     (See accompanying file LICENSE_1_0.txt or copy at
++           http://www.boost.org/LICENSE_1_0.txt)
++/
+module bindbc.lua.v51.types;
+
+version(LUA_51):
+
+import core.stdc.stdio: BUFSIZ;
+
+// luaconf.h
+enum LUA_IDSIZE = 60;
+alias LUAI_UINT32 = uint;
+alias LUAI_INT32 = int;
+enum LUAI_MAXINT32 = int.max;
+alias LUAI_UMEM = size_t;
+alias LUAI_MEM = ptrdiff_t;
+alias LUA_NUMBER = double;
+alias LUA_INTEGER = ptrdiff_t;
+
+enum LUAL_BUFFERSIZE = BUFSIZ;
+
+enum LUAI_MAXSTACK = 1000000;
+
+// lauxlib.h
+enum LUA_ERRFILE = LUA_ERRERR+1;
+
+struct luaL_Reg{
+	const(char)* name;
+	lua_CFunction func;
+}
+
+enum LUA_NOREF = -2;
+enum LUA_REFNIL = -1;
+
+struct luaL_Buffer{
+	char* p;
+	int lvl;
+	lua_State* L;
+	char[LUAL_BUFFERSIZE] buffer;
+}
+
+// lua.h
+// The 5.1 header does not define LUA_VERSION_MAJOR/MINOR/NUM/RELEASE, but we will
+// for consistency with the other versions.
+enum LUA_VERSION_MAJOR = "5";
+enum LUA_VERSION_MINOR = "1";
+enum LUA_VERSION_NUM = 501;
+enum LUA_VERSION_RELEASE = 5;
+
+enum LUA_VERSION = "Lua " ~ LUA_VERSION_MAJOR ~ "." ~ LUA_VERSION_MINOR;
+enum LUA_RELEASE = LUA_VERSION ~ "." ~ LUA_VERSION_RELEASE;
+
+enum LUA_SIGNATURE = "\033Lua";
+enum LUA_MULTRET = -1;
+
+enum LUA_REGISTRYINDEX = -10_000;
+enum LUA_ENVIRONINDEX = -10_001;
+enum LUA_GLOBALSINDEX = -10_002;
+
+enum LUA_YIELD = 1;
+enum LUA_ERRRUN = 2;
+enum LUA_ERRSYNTAX = 3;
+enum LUA_ERRMEM = 4;
+enum LUA_ERRERR = 5;
+
+struct lua_State;
+
+extern(C) nothrow{
+	alias lua_CFunction = int function(lua_State*);
+	alias lua_Reader = const(char)* function(lua_State*, void*, size_t*);
+	alias lua_Writer = int function(lua_State*, const(void)*, size_t, void*);
+	alias lua_Alloc = void* function(void*, void*, size_t, size_t);
+}
+
+enum LUA_TNONE = -1;
+enum LUA_TNIL = 0;
+enum LUA_TBOOLEAN = 1;
+enum LUA_TLIGHTUSERDATA = 2;
+enum LUA_TNUMBER = 3;
+enum LUA_TSTRING = 4;
+enum LUA_TTABLE = 5;
+enum LUA_TFUNCTION = 6;
+enum LUA_TUSERDATA = 7;
+enum LUA_TTHREAD = 8;
+
+enum LUA_MINSTACK = 20;
+
+alias lua_Number = LUA_NUMBER;
+alias lua_Integer = LUA_INTEGER;
+
+enum LUA_GCSTOP = 0;
+enum LUA_GCRESTART = 1;
+enum LUA_GCCOLLECT = 2;
+enum LUA_GCCOUNT = 3;
+enum LUA_GCCOUNTB = 4;
+enum LUA_GCSTEP = 5;
+enum LUA_GCSETPAUSE = 6;
+enum LUA_GCSETSTEPMUL = 7;
+
+enum LUA_HOOKCALL = 0;
+enum LUA_HOOKRET = 1;
+enum LUA_HOOKLINE = 2;
+enum LUA_HOOKCOUNT = 3;
+enum LUA_HOOKTAILRET = 4;
+
+enum LUA_MASKCALL = 1 << LUA_HOOKCALL;
+enum LUA_MASKRET = 1 << LUA_HOOKRET;
+enum LUA_MASKLINE = 1 << LUA_HOOKLINE;
+enum LUA_MASKCOUNT = 1 << LUA_HOOKCOUNT;
+
+struct lua_Debug{
+	int event;
+	const(char)* name;
+	const(char)* namewhat;
+	const(char)* what;
+	const(char)* source;
+	int currentline;
+	int nups;
+	int linedefined;
+	int lastlinedefined;
+	char[LUA_IDSIZE] short_src;
+	private int i_ci;
+}
+
+alias lua_Hook = extern(C) void function(lua_State*, lua_Debug*) nothrow;
+
+// lualib.h
+enum LUA_FILEHANDLE = "FILE*";
+enum LUA_COLIBNAME = "coroutine";
+enum LUA_TABLIBNAME = "table";
+enum LUA_IOLIBNAME = "io";
+enum LUA_OSLIBNAME = "os";
+enum LUA_STRLIBNAME = "string";
+enum LUA_MATHLIBNAME = "math";
+enum LUA_DBLIBNAME = "debug";
+enum LUA_LOADLIBNAME = "package";

+ 536 - 0
source/bindbc/lua/v52/binddynamic.d

@@ -0,0 +1,536 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua.v52.binddynamic;
+
+version(BindBC_Static) version = BindLua_Static;
+version(BindLua_Static) {}
+else version = BindLua_Dynamic;
+
+version(LUA_52) {
+    version(BindLua_Dynamic) version = LUA_52_DYNAMIC;
+}
+
+version(LUA_52_DYNAMIC):
+
+import core.stdc.stdarg : va_list;
+import bindbc.loader;
+import bindbc.lua.config;
+import bindbc.lua.v52.types;
+
+extern(C) @nogc nothrow {
+    // lauxlib.h
+    alias pluaL_checkversion_ = void function(lua_State* L, lua_Number ver);
+    alias pluaL_getmetafield = int function(lua_State* L, int obj, const(char)* e);
+    alias pluaL_callmeta = int function(lua_State* L, int obj, const(char)* e);
+    alias pluaL_tolstring = const(char)* function(lua_State* L, int idx, size_t* len);
+    alias pluaL_argerror = int function(lua_State* L, int numarg, const(char)* extramsg);
+    alias pluaL_checklstring = const(char)* function(lua_State* L, int numArg, size_t* l);
+    alias pluaL_optlstring = const(char)* function(lua_State* L, int numArg, const(char)* def, size_t* l);
+    alias pluaL_checknumber = lua_Number function(lua_State* L, int numArg);
+    alias pluaL_optnumber = lua_Number function(lua_State* L, int nArg, lua_Number def);
+    alias pluaL_checkinteger = lua_Integer function(lua_State* L, int numArg);
+    alias pluaL_optinteger = lua_Integer function(lua_State* L, int nArg, lua_Integer def);
+    alias pluaL_checkunsigned = lua_Unsigned function(lua_State* L, int numArg);
+    alias pluaL_optunsigned = lua_Unsigned function(lua_State* L, int numArg, lua_Unsigned def);
+    alias pluaL_checkstack = void function(lua_State* L, int sz, const(char)* msg);
+    alias pluaL_checktype = void function(lua_State* L, int narg, int t);
+    alias pluaL_checkany = void function(lua_State* L, int narg);
+    alias pluaL_newmetatable = int function(lua_State* L, const(char)* tname);
+    alias pluaL_setmetatable = void function(lua_State* L, const(char)* tname);
+    alias pluaL_testudata = void* function(lua_State* L, int ud, const(char)* tname);
+    alias pluaL_checkudata = void* function(lua_State* L, int ud, const(char)* tname);
+    alias pluaL_where = void function(lua_State* L, int lvl);
+    alias pluaL_error = int function(lua_State* L, const(char)* fmt, ...);
+    alias pluaL_checkoption = int function(lua_State* L, int narg, const(char)* def, const(char)** lst);
+    alias pluaL_fileresult = int function(lua_State* L, int stat, const(char)* fname);
+    alias pluaL_execresult = int function(lua_State* L, int stat);
+    alias pluaL_ref = int function(lua_State* L, int t);
+    alias pluaL_unref = void function(lua_State* L, int t, int ref_);
+    alias pluaL_loadfilex = int function(lua_State* L, const(char)* filename, const(char)* mode);
+    alias pluaL_loadbufferx = int function(lua_State* L, const(char)* buff, size_t sz, const(char)* name, const(char)* mode);
+    alias pluaL_loadstring = int function(lua_State* L, const(char)* s);
+    alias pluaL_newstate = lua_State* function();
+    alias pluaL_len = int function(lua_State* L, int idx);
+    alias pluaL_gsub = const(char)* function(lua_State* L, const(char)* s, const(char)* p, const(char)* r);
+    alias pluaL_setfuncs = void function(lua_State* L, const(luaL_Reg)* l, int nup);
+    alias pluaL_getsubtable = int function(lua_State* L, int idx, const(char)* fname);
+    alias pluaL_traceback = void function(lua_State* L, lua_State* L1, const(char)* msg, int level);
+    alias pluaL_requiref = void function(lua_State* L, const(char)*, lua_CFunction openf, int glb);
+    alias pluaL_buffinit = void function(lua_State* L, luaL_Buffer* B);
+    alias pluaL_prepbuffsize = char* function(luaL_Buffer* B, size_t sz);
+    alias pluaL_addlstring = void function(luaL_Buffer* B, const(char)* s, size_t l);
+    alias pluaL_addstring = void function(luaL_Buffer* B,  const(char)* s);
+    alias pluaL_addvalue = void function(luaL_Buffer* B);
+    alias pluaL_pushresult = void function(luaL_Buffer* B);
+    alias pluaL_pushresultsize = void function(luaL_Buffer* B, size_t sz);
+    alias pluaL_buffinitsize = char* function(lua_State* L, luaL_Buffer* B, size_t sz);
+
+    // lua.h
+    alias plua_newstate = lua_State* function(lua_Alloc f, void* ud);
+    alias plua_close = void function(lua_State* L);
+    alias plua_newthread = lua_State* function(lua_State* L);
+    alias plua_atpanic = lua_CFunction function(lua_State* L, lua_CFunction panicf);
+    alias plua_version = const(lua_Number)* function(lua_State* L);
+    alias plua_absindex = int function(lua_State* L, int idx);
+    alias plua_gettop = int function(lua_State* L);
+    alias plua_settop = void function(lua_State* L, int idx);
+    alias plua_pushvalue = void function(lua_State* L, int idx);
+    alias plua_remove = void function(lua_State* L, int idx);
+    alias plua_insert = void function(lua_State* L, int idx);
+    alias plua_replace = void function(lua_State* L, int idx);
+    alias plua_copy = void function(lua_State* L, int fromidx, int toidx);
+    alias plua_checkstack = int function(lua_State* L, int sz);
+    alias plua_xmove = void function(lua_State* from, lua_State* to, int n);
+    alias plua_isnumber = int function(lua_State* L, int idx);
+    alias plua_isstring = int function(lua_State* L, int idx);
+    alias plua_iscfunction = int function(lua_State* L, int idx);
+    alias plua_isuserdata = int function(lua_State* L, int idx);
+    alias plua_type = int function(lua_State* L, int idx);
+    alias plua_typename = const(char)* function(lua_State* L, int tp);
+    alias plua_tonumberx = lua_Number function(lua_State* L, int idx, int* isnum);
+    alias plua_tointegerx = lua_Integer function(lua_State* L, int idx, int* isnum);
+    alias plua_tounsignedx = lua_Unsigned function(lua_State* L, int idx, int* isnum);
+    alias plua_toboolean = int function(lua_State* L, int idx);
+    alias plua_tolstring = const(char)* function(lua_State* L, int idx, size_t* len);
+    alias plua_rawlen = size_t function(lua_State* L, int idx);
+    alias plua_tocfunction = lua_CFunction function(lua_State* L, int idx);
+    alias plua_touserdata = void* function(lua_State* L, int idx);
+    alias plua_tothread = lua_State* function(lua_State* L, int idx);
+    alias plua_topointer = const(void)* function(lua_State* L, int idx);
+    alias plua_arith = void function(lua_State* L, int op);
+    alias plua_rawequal = int function(lua_State* L, int idx1, int idx2);
+    alias plua_compare = int function(lua_State* L, int idx1, int idx2, int op);
+    alias plua_pushnil = void function(lua_State* L);
+    alias plua_pushnumber = void function(lua_State* L, lua_Number n);
+    alias plua_pushinteger = void function(lua_State* L, lua_Integer n);
+    alias plua_pushunsigned = void function(lua_State* L, lua_Unsigned n);
+    alias plua_pushlstring = const(char)*  function(lua_State* L, const(char)* s, size_t l);
+    alias plua_pushstring = const(char)*  function(lua_State* L, const(char)* s);
+    alias plua_pushvfstring = const(char)* function(lua_State* L, const(char)* fmt, va_list argp);
+    alias plua_pushfstring = const(char)* function(lua_State* L, const(char)* fmt, ...);
+    alias plua_pushcclosure = void function(lua_State* L, lua_CFunction fn, int n);
+    alias plua_pushboolean = void function(lua_State* L, int b);
+    alias plua_pushlightuserdata = void function(lua_State* L, void* p);
+    alias plua_pushthread = int function(lua_State* L);
+    alias plua_getglobal = void function(lua_State* L, const(char)* var);
+    alias plua_gettable = void function(lua_State* L, int idx);
+    alias plua_getfield = void function(lua_State* L, int idx, const(char)* k);
+    alias plua_rawget = void function(lua_State* L, int idx);
+    alias plua_rawgeti = void function(lua_State* L, int idx, int n);
+    alias plua_rawgetp = void function(lua_State* L, int idx, const(void)* p);
+    alias plua_createtable = void function(lua_State* L, int narr, int nrec);
+    alias plua_newuserdata = void* function(lua_State* L, size_t sz);
+    alias plua_getmetatable = int function(lua_State* L, int objindex);
+    alias plua_getuservalue = void function(lua_State* L, int idx);
+    alias plua_setglobal = void function(lua_State* L, const(char)* var);
+    alias plua_settable = void function(lua_State* L, int idx);
+    alias plua_setfield = void function(lua_State* L, int idx, const(char)* k);
+    alias plua_rawset = void function(lua_State* L, int idx);
+    alias plua_rawseti = void function(lua_State* L, int idx, int n);
+    alias plua_rawsetp = void function(lua_State* L, int idx, const(void)* p);
+    alias plua_setmetatable = int function(lua_State* L, int objindex);
+    alias plua_setuservalue = int function(lua_State* L, int idx);
+    alias plua_callk = void function(lua_State* L, int nargs, int nresults, int ctx, lua_CFunction k);
+    alias plua_getctx = int function(lua_State* L, int* ctx);
+    alias plua_pcallk = int function(lua_State* L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k);
+    alias plua_load = int function(lua_State* L, lua_Reader reader, void* dt, const(char)* chunkname, const(char)* mode);
+    alias plua_dump = int function(lua_State* L, lua_Writer writer, void* data);
+    alias plua_yieldk = int function(lua_State* L, int nresults, int ctx, lua_CFunction k);
+    alias plua_resume = int function(lua_State* L, lua_State* from, int narg);
+    alias plua_status = int function(lua_State* L);
+    alias plua_gc = int function(lua_State* L, int what, int data);
+    alias plua_error = int function(lua_State* L);
+    alias plua_next = int function(lua_State* L, int idx);
+    alias plua_concat = void function(lua_State* L, int n);
+    alias plua_len = void function(lua_State* L, int idx);
+    alias plua_getallocf = lua_Alloc function(lua_State* L, void** ud);
+    alias plua_setallocf = void function(lua_State* L, lua_Alloc f, void* ud);
+    alias plua_getstack = int function(lua_State* L, int level, lua_Debug* ar);
+    alias plua_getinfo = int function(lua_State* L, const(char)* what, lua_Debug* ar);
+    alias plua_getlocal = const(char)* function(lua_State* L, const(lua_Debug)* ar, int n);
+    alias plua_setlocal = const(char)* function(lua_State* L, const(lua_Debug)* ar, int n);
+    alias plua_getupvalue = const(char)* function(lua_State* L, int funcindex, int n);
+    alias plua_setupvalue = const(char)* function(lua_State* L, int funcindex, int n);
+    alias plua_upvalueid = void* function(lua_State* L, int fidx, int n);
+    alias plua_upvaluejoin = void function(lua_State* L, int fidx1, int n1, int fidx2, int n2);
+    alias plua_sethook = int function(lua_State* L, lua_Hook func, int mask, int count);
+    alias plua_gethook = lua_Hook function(lua_State* L);
+    alias plua_gethookmask = int function(lua_State* L);
+    alias plua_gethookcount = int function(lua_State* L);
+
+    // lualib.h
+    alias pluaopen_base = int function(lua_State* L);
+    alias pluaopen_coroutine = int function(lua_State* L);
+    alias pluaopen_table = int function(lua_State* L);
+    alias pluaopen_io = int function(lua_State* L);
+    alias pluaopen_os = int function(lua_State* L);
+    alias pluaopen_string = int function(lua_State* L);
+    alias pluaopen_bit32 = int function(lua_State* L);
+    alias pluaopen_math = int function(lua_State* L);
+    alias pluaopen_debug = int function(lua_State* L);
+    alias pluaopen_package = int function(lua_State* L);
+    alias pluaL_openlibs = void function(lua_State* L);
+}
+
+__gshared {
+    // lauxlib.h
+    pluaL_checkversion_ luaL_checkversion_;
+    pluaL_getmetafield luaL_getmetafield;
+    pluaL_callmeta luaL_callmeta;
+    pluaL_tolstring luaL_tolstring;
+    pluaL_argerror luaL_argerror;
+    pluaL_checklstring luaL_checklstring;
+    pluaL_optlstring luaL_optlstring;
+    pluaL_checknumber luaL_checknumber;
+    pluaL_optnumber luaL_optnumber;
+    pluaL_checkinteger luaL_checkinteger;
+    pluaL_optinteger luaL_optinteger;
+    pluaL_checkunsigned luaL_checkunsigned;
+    pluaL_optunsigned luaL_optunsigned;
+    pluaL_checkstack luaL_checkstack;
+    pluaL_checktype luaL_checktype;
+    pluaL_checkany luaL_checkany;
+    pluaL_newmetatable luaL_newmetatable;
+    pluaL_setmetatable luaL_setmetatable;
+    pluaL_testudata luaL_testudata;
+    pluaL_checkudata luaL_checkudata;
+    pluaL_where luaL_where;
+    pluaL_error luaL_error;
+    pluaL_checkoption luaL_checkoption;
+    pluaL_fileresult luaL_fileresult;
+    pluaL_execresult luaL_execresult;
+    pluaL_ref luaL_ref;
+    pluaL_unref luaL_unref;
+    pluaL_loadfilex luaL_loadfilex;
+    pluaL_loadbufferx luaL_loadbufferx;
+    pluaL_loadstring luaL_loadstring;
+    pluaL_newstate luaL_newstate;
+    pluaL_len luaL_len;
+    pluaL_gsub luaL_gsub;
+    pluaL_setfuncs luaL_setfuncs;
+    pluaL_getsubtable luaL_getsubtable;
+    pluaL_traceback luaL_traceback;
+    pluaL_requiref luaL_requiref;
+    pluaL_buffinit luaL_buffinit;
+    pluaL_prepbuffsize luaL_prepbuffsize;
+    pluaL_addlstring luaL_addlstring;
+    pluaL_addstring luaL_addstring;
+    pluaL_addvalue luaL_addvalue;
+    pluaL_pushresult luaL_pushresult;
+    pluaL_pushresultsize luaL_pushresultsize;
+    pluaL_buffinitsize luaL_buffinitsize;
+
+    // lua.h
+    plua_newstate lua_newstate;
+    plua_close lua_close;
+    plua_newthread lua_newthread;
+    plua_atpanic lua_atpanic;
+    plua_version lua_version;
+    plua_absindex lua_absindex;
+    plua_gettop lua_gettop;
+    plua_settop lua_settop;
+    plua_pushvalue lua_pushvalue;
+    plua_remove lua_remove;
+    plua_insert lua_insert;
+    plua_replace lua_replace;
+    plua_copy lua_copy;
+    plua_checkstack lua_checkstack;
+    plua_xmove lua_xmove;
+    plua_isnumber lua_isnumber;
+    plua_isstring lua_isstring;
+    plua_iscfunction lua_iscfunction;
+    plua_isuserdata lua_isuserdata;
+    plua_type lua_type;
+    plua_typename lua_typename;
+    plua_tonumberx lua_tonumberx;
+    plua_tointegerx lua_tointegerx;
+    plua_tounsignedx lua_tounsignedx;
+    plua_toboolean lua_toboolean;
+    plua_tolstring lua_tolstring;
+    plua_rawlen lua_rawlen;
+    plua_tocfunction lua_tocfunction;
+    plua_touserdata lua_touserdata;
+    plua_tothread lua_tothread;
+    plua_topointer lua_topointer;
+    plua_arith lua_arith;
+    plua_rawequal lua_rawequal;
+    plua_compare lua_compare;
+    plua_pushnil lua_pushnil;
+    plua_pushnumber lua_pushnumber;
+    plua_pushinteger lua_pushinteger;
+    plua_pushunsigned lua_pushunsigned;
+    plua_pushlstring lua_pushlstring;
+    plua_pushstring lua_pushstring;
+    plua_pushvfstring lua_pushvfstring;
+    plua_pushfstring lua_pushfstring;
+    plua_pushcclosure lua_pushcclosure;
+    plua_pushboolean lua_pushboolean;
+    plua_pushlightuserdata lua_pushlightuserdata;
+    plua_pushthread lua_pushthread;
+    plua_getglobal lua_getglobal;
+    plua_gettable lua_gettable;
+    plua_getfield lua_getfield;
+    plua_rawget lua_rawget;
+    plua_rawgeti lua_rawgeti;
+    plua_rawgetp lua_rawgetp;
+    plua_createtable lua_createtable;
+    plua_newuserdata lua_newuserdata;
+    plua_getmetatable lua_getmetatable;
+    plua_getuservalue lua_getuservalue;
+    plua_setglobal lua_setglobal;
+    plua_settable lua_settable;
+    plua_setfield lua_setfield;
+    plua_rawset lua_rawset;
+    plua_rawseti lua_rawseti;
+    plua_rawsetp lua_rawsetp;
+    plua_setmetatable lua_setmetatable;
+    plua_setuservalue lua_setuservalue;
+    plua_callk lua_callk;
+    plua_getctx lua_getctx;
+    plua_pcallk lua_pcallk;
+    plua_load lua_load;
+    plua_dump lua_dump;
+    plua_yieldk lua_yieldk;
+    plua_resume lua_resume;
+    plua_status lua_status;
+    plua_gc lua_gc;
+    plua_error lua_error;
+    plua_next lua_next;
+    plua_concat lua_concat;
+    plua_len lua_len;
+    plua_getallocf lua_getallocf;
+    plua_setallocf lua_setallocf;
+    plua_getstack lua_getstack;
+    plua_getinfo lua_getinfo;
+    plua_getlocal lua_getlocal;
+    plua_setlocal lua_setlocal;
+    plua_getupvalue lua_getupvalue;
+    plua_setupvalue lua_setupvalue;
+    plua_upvalueid lua_upvalueid;
+    plua_upvaluejoin lua_upvaluejoin;
+    plua_sethook lua_sethook;
+    plua_gethook lua_gethook;
+    plua_gethookmask lua_gethookmask;
+    plua_gethookcount lua_gethookcount;
+
+    // lualib.h
+    pluaopen_base luaopen_base;
+    pluaopen_coroutine luaopen_coroutine;
+    pluaopen_table luaopen_table;
+    pluaopen_io luaopen_io;
+    pluaopen_os luaopen_os;
+    pluaopen_string luaopen_string;
+    pluaopen_bit32 luaopen_bit32;
+    pluaopen_math luaopen_math;
+    pluaopen_debug luaopen_debug;
+    pluaopen_package luaopen_package;
+    pluaL_openlibs luaL_openlibs;
+}
+
+private {
+    SharedLib lib;
+    LuaSupport loadedVersion;
+}
+
+@nogc nothrow:
+
+void unloadLua()
+{
+    if(lib != invalidHandle) {
+        lib.unload;
+    }
+}
+
+LuaSupport loadedLuaVersion() @safe { return loadedVersion; }
+bool isLuaLoaded() @safe { return lib != invalidHandle; }
+
+LuaSupport loadLua()
+{
+    version(Windows) {
+        const(char)[][3] libNames = ["lua5.2.dll", "lua52.dll", "lua5.2.4.dll"];
+    }
+    else version(OSX) {
+        const(char)[][1] libNames = "liblua.5.2.dylib";
+    }
+    else version(Posix) {
+        const(char)[][3] libNames = ["liblua.so.5.2", "liblua5.2.so", "liblua-5.2.so"];
+    }
+    else static assert(0, "bindbc-lua support for Lua 5.2 is not implemented on this platform.");
+
+    LuaSupport ret;
+    foreach(name; libNames) {
+        ret = loadLua(name.ptr);
+        if(ret != LuaSupport.noLibrary) break;
+    }
+    return ret;
+}
+
+LuaSupport loadLua(const(char)* libName)
+{
+    lib = load(libName);
+    if(lib == invalidHandle) {
+        return LuaSupport.noLibrary;
+    }
+
+    auto errCount = errorCount();
+    loadedVersion = LuaSupport.badLibrary;
+
+    // lauxlib.h
+    lib.bindSymbol(cast(void**)&luaL_checkversion_, "luaL_checkversion_");
+    lib.bindSymbol(cast(void**)&luaL_getmetafield,"luaL_getmetafield");
+    lib.bindSymbol(cast(void**)&luaL_callmeta, "luaL_callmeta");
+    lib.bindSymbol(cast(void**)&luaL_tolstring, "luaL_tolstring");
+    lib.bindSymbol(cast(void**)&luaL_argerror, "luaL_argerror");
+    lib.bindSymbol(cast(void**)&luaL_checklstring, "luaL_checklstring");
+    lib.bindSymbol(cast(void**)&luaL_optlstring, "luaL_optlstring");
+    lib.bindSymbol(cast(void**)&luaL_checknumber, "luaL_checknumber");
+    lib.bindSymbol(cast(void**)&luaL_optnumber, "luaL_optnumber");
+    lib.bindSymbol(cast(void**)&luaL_checkinteger, "luaL_checkinteger");
+    lib.bindSymbol(cast(void**)&luaL_optinteger, "luaL_optinteger");
+    lib.bindSymbol(cast(void**)&luaL_checkunsigned, "luaL_checkunsigned");
+    lib.bindSymbol(cast(void**)&luaL_optunsigned,"luaL_optunsigned");
+    lib.bindSymbol(cast(void**)&luaL_checkstack, "luaL_checkstack");
+    lib.bindSymbol(cast(void**)&luaL_checktype, "luaL_checktype");
+    lib.bindSymbol(cast(void**)&luaL_checkany, "luaL_checkany");
+    lib.bindSymbol(cast(void**)&luaL_newmetatable, "luaL_newmetatable");
+    lib.bindSymbol(cast(void**)&luaL_setmetatable, "luaL_setmetatable");
+    lib.bindSymbol(cast(void**)&luaL_testudata, "luaL_testudata");
+    lib.bindSymbol(cast(void**)&luaL_checkudata, "luaL_checkudata");
+    lib.bindSymbol(cast(void**)&luaL_where, "luaL_where");
+    lib.bindSymbol(cast(void**)&luaL_error, "luaL_error");
+    lib.bindSymbol(cast(void**)&luaL_checkoption, "luaL_checkoption");
+    lib.bindSymbol(cast(void**)&luaL_fileresult, "luaL_fileresult");
+    lib.bindSymbol(cast(void**)&luaL_execresult, "luaL_execresult");
+    lib.bindSymbol(cast(void**)&luaL_ref, "luaL_ref");
+    lib.bindSymbol(cast(void**)&luaL_unref, "luaL_unref");
+    lib.bindSymbol(cast(void**)&luaL_loadfilex, "luaL_loadfilex");
+    lib.bindSymbol(cast(void**)&luaL_loadbufferx, "luaL_loadbufferx");
+    lib.bindSymbol(cast(void**)&luaL_loadstring, "luaL_loadstring");
+    lib.bindSymbol(cast(void**)&luaL_newstate, "luaL_newstate");
+    lib.bindSymbol(cast(void**)&luaL_len, "luaL_len");
+    lib.bindSymbol(cast(void**)&luaL_gsub, "luaL_gsub");
+    lib.bindSymbol(cast(void**)&luaL_setfuncs, "luaL_setfuncs");
+    lib.bindSymbol(cast(void**)&luaL_getsubtable, "luaL_getsubtable");
+    lib.bindSymbol(cast(void**)&luaL_traceback, "luaL_traceback");
+    lib.bindSymbol(cast(void**)&luaL_requiref, "luaL_requiref");
+    lib.bindSymbol(cast(void**)&luaL_buffinit, "luaL_buffinit");
+    lib.bindSymbol(cast(void**)&luaL_prepbuffsize, "luaL_prepbuffsize");
+    lib.bindSymbol(cast(void**)&luaL_addlstring, "luaL_addlstring");
+    lib.bindSymbol(cast(void**)&luaL_addstring, "luaL_addstring");
+    lib.bindSymbol(cast(void**)&luaL_addvalue, "luaL_addvalue");
+    lib.bindSymbol(cast(void**)&luaL_pushresult, "luaL_pushresult");
+    lib.bindSymbol(cast(void**)&luaL_pushresultsize, "luaL_pushresultsize");
+    lib.bindSymbol(cast(void**)&luaL_buffinitsize, "luaL_buffinitsize");
+
+    // lua.h
+    lib.bindSymbol(cast(void**)&lua_newstate, "lua_newstate");
+    lib.bindSymbol(cast(void**)&lua_close, "lua_close");
+    lib.bindSymbol(cast(void**)&lua_newthread, "lua_newthread");
+    lib.bindSymbol(cast(void**)&lua_atpanic, "lua_atpanic");
+    lib.bindSymbol(cast(void**)&lua_version, "lua_version");
+    lib.bindSymbol(cast(void**)&lua_absindex, "lua_absindex");
+    lib.bindSymbol(cast(void**)&lua_gettop, "lua_gettop");
+    lib.bindSymbol(cast(void**)&lua_settop, "lua_settop");
+    lib.bindSymbol(cast(void**)&lua_pushvalue, "lua_pushvalue");
+    lib.bindSymbol(cast(void**)&lua_remove, "lua_remove");
+    lib.bindSymbol(cast(void**)&lua_copy, "lua_copy");
+    lib.bindSymbol(cast(void**)&lua_insert, "lua_insert");
+    lib.bindSymbol(cast(void**)&lua_replace, "lua_replace");
+    lib.bindSymbol(cast(void**)&lua_checkstack, "lua_checkstack");
+    lib.bindSymbol(cast(void**)&lua_xmove, "lua_xmove");
+    lib.bindSymbol(cast(void**)&lua_isnumber, "lua_isnumber");
+    lib.bindSymbol(cast(void**)&lua_isstring, "lua_isstring");
+    lib.bindSymbol(cast(void**)&lua_iscfunction, "lua_iscfunction");
+    lib.bindSymbol(cast(void**)&lua_isuserdata, "lua_isuserdata");
+    lib.bindSymbol(cast(void**)&lua_type, "lua_type");
+    lib.bindSymbol(cast(void**)&lua_typename, "lua_typename");
+    lib.bindSymbol(cast(void**)&lua_tonumberx, "lua_tonumberx");
+    lib.bindSymbol(cast(void**)&lua_tointegerx, "lua_tointegerx");
+    lib.bindSymbol(cast(void**)&lua_tounsignedx, "lua_tounsignedx");
+    lib.bindSymbol(cast(void**)&lua_toboolean, "lua_toboolean");
+    lib.bindSymbol(cast(void**)&lua_tolstring, "lua_tolstring");
+    lib.bindSymbol(cast(void**)&lua_rawlen, "lua_rawlen");
+    lib.bindSymbol(cast(void**)&lua_tocfunction, "lua_tocfunction");
+    lib.bindSymbol(cast(void**)&lua_touserdata, "lua_touserdata");
+    lib.bindSymbol(cast(void**)&lua_tothread, "lua_tothread");
+    lib.bindSymbol(cast(void**)&lua_topointer, "lua_topointer");
+    lib.bindSymbol(cast(void**)&lua_arith, "lua_arith");
+    lib.bindSymbol(cast(void**)&lua_rawequal, "lua_rawequal");
+    lib.bindSymbol(cast(void**)&lua_compare, "lua_compare");
+    lib.bindSymbol(cast(void**)&lua_pushnil, "lua_pushnil");
+    lib.bindSymbol(cast(void**)&lua_pushnumber, "lua_pushnumber");
+    lib.bindSymbol(cast(void**)&lua_pushinteger, "lua_pushinteger");
+    lib.bindSymbol(cast(void**)&lua_pushunsigned, "lua_pushunsigned");
+    lib.bindSymbol(cast(void**)&lua_pushlstring, "lua_pushlstring");
+    lib.bindSymbol(cast(void**)&lua_pushstring, "lua_pushstring");
+    lib.bindSymbol(cast(void**)&lua_pushvfstring, "lua_pushvfstring");
+    lib.bindSymbol(cast(void**)&lua_pushfstring, "lua_pushfstring");
+    lib.bindSymbol(cast(void**)&lua_pushcclosure, "lua_pushcclosure");
+    lib.bindSymbol(cast(void**)&lua_pushboolean, "lua_pushboolean");
+    lib.bindSymbol(cast(void**)&lua_pushlightuserdata, "lua_pushlightuserdata");
+    lib.bindSymbol(cast(void**)&lua_pushthread, "lua_pushthread");
+    lib.bindSymbol(cast(void**)&lua_getglobal, "lua_getglobal");
+    lib.bindSymbol(cast(void**)&lua_gettable, "lua_gettable");
+    lib.bindSymbol(cast(void**)&lua_getfield, "lua_getfield");
+    lib.bindSymbol(cast(void**)&lua_rawget, "lua_rawget");
+    lib.bindSymbol(cast(void**)&lua_rawgeti, "lua_rawgeti");
+    lib.bindSymbol(cast(void**)&lua_rawgetp, "lua_rawgetp");
+    lib.bindSymbol(cast(void**)&lua_createtable, "lua_createtable");
+    lib.bindSymbol(cast(void**)&lua_newuserdata, "lua_newuserdata");
+    lib.bindSymbol(cast(void**)&lua_getmetatable, "lua_getmetatable");
+    lib.bindSymbol(cast(void**)&lua_getuservalue, "lua_getuservalue");
+    lib.bindSymbol(cast(void**)&lua_setglobal, "lua_setglobal");
+    lib.bindSymbol(cast(void**)&lua_settable, "lua_settable");
+    lib.bindSymbol(cast(void**)&lua_setfield, "lua_setfield");
+    lib.bindSymbol(cast(void**)&lua_rawset, "lua_rawset");
+    lib.bindSymbol(cast(void**)&lua_rawseti, "lua_rawseti");
+    lib.bindSymbol(cast(void**)&lua_rawsetp, "lua_rawsetp");
+    lib.bindSymbol(cast(void**)&lua_setmetatable, "lua_setmetatable");
+    lib.bindSymbol(cast(void**)&lua_setuservalue, "lua_setuservalue");
+    lib.bindSymbol(cast(void**)&lua_callk, "lua_callk");
+    lib.bindSymbol(cast(void**)&lua_getctx, "lua_getctx");
+    lib.bindSymbol(cast(void**)&lua_pcallk, "lua_pcallk");
+    lib.bindSymbol(cast(void**)&lua_load, "lua_load");
+    lib.bindSymbol(cast(void**)&lua_dump, "lua_dump");
+    lib.bindSymbol(cast(void**)&lua_yieldk, "lua_yieldk");
+    lib.bindSymbol(cast(void**)&lua_resume, "lua_resume");
+    lib.bindSymbol(cast(void**)&lua_status, "lua_status");
+    lib.bindSymbol(cast(void**)&lua_gc, "lua_gc");
+    lib.bindSymbol(cast(void**)&lua_error, "lua_error");
+    lib.bindSymbol(cast(void**)&lua_next, "lua_next");
+    lib.bindSymbol(cast(void**)&lua_concat, "lua_concat");
+    lib.bindSymbol(cast(void**)&lua_len, "lua_len");
+    lib.bindSymbol(cast(void**)&lua_getallocf, "lua_getallocf");
+    lib.bindSymbol(cast(void**)&lua_setallocf, "lua_setallocf");
+    lib.bindSymbol(cast(void**)&lua_getstack, "lua_getstack");
+    lib.bindSymbol(cast(void**)&lua_getinfo, "lua_getinfo");
+    lib.bindSymbol(cast(void**)&lua_getlocal, "lua_getlocal");
+    lib.bindSymbol(cast(void**)&lua_setlocal, "lua_setlocal");
+    lib.bindSymbol(cast(void**)&lua_getupvalue, "lua_getupvalue");
+    lib.bindSymbol(cast(void**)&lua_setupvalue, "lua_setupvalue");
+    lib.bindSymbol(cast(void**)&lua_upvalueid, "lua_upvalueid");
+    lib.bindSymbol(cast(void**)&lua_upvaluejoin, "lua_upvaluejoin");
+    lib.bindSymbol(cast(void**)&lua_sethook, "lua_sethook");
+    lib.bindSymbol(cast(void**)&lua_gethook, "lua_gethook");
+    lib.bindSymbol(cast(void**)&lua_gethookmask, "lua_gethookmask");
+    lib.bindSymbol(cast(void**)&lua_gethookcount, "lua_gethookcount");
+
+    // lualib.h
+    lib.bindSymbol(cast(void**)&luaopen_base, "luaopen_base");
+    lib.bindSymbol(cast(void**)&luaopen_coroutine, "luaopen_coroutine");
+    lib.bindSymbol(cast(void**)&luaopen_table, "luaopen_table");
+    lib.bindSymbol(cast(void**)&luaopen_io, "luaopen_io");
+    lib.bindSymbol(cast(void**)&luaopen_os, "luaopen_os");
+    lib.bindSymbol(cast(void**)&luaopen_string, "luaopen_string");
+    lib.bindSymbol(cast(void**)&luaopen_bit32, "luaopen_bit32");
+    lib.bindSymbol(cast(void**)&luaopen_math, "luaopen_math");
+    lib.bindSymbol(cast(void**)&luaopen_debug, "luaopen_debug");
+    lib.bindSymbol(cast(void**)&luaopen_package, "luaopen_package");
+    lib.bindSymbol(cast(void**)&luaL_openlibs, "luaL_openlibs");
+
+    return LuaSupport.lua52;
+}

+ 172 - 0
source/bindbc/lua/v52/bindstatic.d

@@ -0,0 +1,172 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua.v52.bindstatic;
+
+
+version(BindBC_Static) version = BindLua_Static;
+version(BindLua_Static) {
+    version(LUA_52) version = LUA_52_STATIC;
+}
+
+version(LUA_52_STATIC):
+
+import core.stdc.stdarg : va_list;
+import bindbc.lua.v52.types;
+
+extern(C) @nogc nothrow:
+    // lauxlib.h
+    void luaL_checkversion_(lua_State* L, lua_Number ver);
+    int luaL_getmetafield(lua_State* L, int obj, const(char)* e);
+    int luaL_callmeta(lua_State* L,  int obj, const(char)* e);
+    const(char)* luaL_tolstring(lua_State* L, int idx, size_t* len);
+    int luaL_argerror(lua_State* L, int numarg, const(char)* extramsg);
+    const(char)* luaL_checklstring(lua_State* L, int numArg, size_t* l);
+    const(char)* luaL_optlstring(lua_State* L, int numArg, const(char)* def, size_t* l);
+    lua_Number luaL_checknumber(lua_State* L, int numArg);
+    lua_Number luaL_optnumber(lua_State* L, int nArg, lua_Number def);
+    lua_Integer luaL_checkinteger(lua_State* L, int numArg);
+    lua_Integer luaL_optinteger(lua_State* L, int nArg, lua_Integer def);
+    lua_Unsigned luaL_checkunsigned(lua_State* L, int numArg);
+    lua_Unsigned luaL_optunsigned(lua_State* L, int numArg, lua_Unsigned def);
+    void luaL_checkstack(lua_State* L, int sz, const(char)* msg);
+    void luaL_checktype(lua_State* L, int narg, int t);
+    void luaL_checkany(lua_State* L, int narg);
+    int luaL_newmetatable(lua_State* L, const(char)* tname);
+    void luaL_setmetatable(lua_State* L, const(char)* tname);
+    void* luaL_testudata(lua_State* L, int ud, const(char)* tname);
+    void* luaL_checkudata(lua_State* L, int ud, const(char)* tname);
+    void luaL_where(lua_State* L, int lvl);
+    int luaL_error(lua_State* L, const(char)* fmt, ...);
+    int luaL_checkoption(lua_State* L, int narg, const(char)* def, const(char)** lst);
+    int luaL_fileresult(lua_State* L, int stat, const(char)* fname);
+    int luaL_execresult(lua_State* L, int stat);
+    int luaL_ref(lua_State* L, int t);
+    void luaL_unref(lua_State* L, int t, int ref_);
+    int luaL_loadfilex(lua_State* L, const(char)* filename, const(char)* mode);
+    int luaL_loadbufferx(lua_State* L, const(char)* buff, size_t sz, const(char)* name, const(char)* mode);
+    int luaL_loadstring(lua_State* L, const(char)* s);
+    lua_State* luaL_newstate();
+    int luaL_len(lua_State* L, int idx);
+    const(char)* luaL_gsub(lua_State* L, const(char)* s, const(char)* p, const(char)* r);
+    void luaL_setfuncs(lua_State* L, const(luaL_Reg)* l, int nup);
+    int luaL_getsubtable(lua_State* L, int idx, const(char)* fname);
+    void luaL_traceback(lua_State* L, lua_State* L1, const(char)* msg, int level);
+    void luaL_requiref(lua_State* L, const(char)* modname, lua_CFunction openf, int glb);
+    void luaL_buffinit(lua_State* L, luaL_Buffer* B);
+    char* luaL_prepbuffsize(luaL_Buffer*, size_t sz);
+    void luaL_addlstring(luaL_Buffer* B, const(char)* s, size_t l);
+    void luaL_addstring(luaL_Buffer* B,  const(char)* s);
+    void luaL_addvalue(luaL_Buffer* B);
+    void luaL_pushresult(luaL_Buffer* B);
+    void luaL_pushresultsize(luaL_Buffer* B, size_t sz);
+    char* luaL_buffinitsize(lua_State* L, luaL_Buffer* B, size_t sz);
+
+    // lua.h
+    lua_State* lua_newstate(lua_Alloc f, void* ud);
+    lua_State* lua_close(lua_State* L);
+    lua_State* lua_newthread(lua_State* L);
+    lua_CFunction lua_atpanic(lua_State* L, lua_CFunction panicf);
+    const(lua_Number)* lua_version(lua_State* L);
+    int lua_absindex(lua_State* L, int idx);
+    int lua_gettop(lua_State* L);
+    void lua_settop(lua_State* L, int idx);
+    void lua_pushvalue(lua_State* L, int idx);
+    void lua_remove(lua_State* L, int idx);
+    void lua_insert(lua_State* L, int idx);
+    void lua_replace(lua_State* L, int idx);
+    void lua_copy(lua_State* L, int fromidx, int toidx);
+    int lua_checkstack(lua_State* L, int sz);
+    void lua_xmove(lua_State* from, lua_State* to, int n);
+    int lua_isnumber(lua_State* L, int idx);
+    int lua_isstring(lua_State* L, int idx);
+    int lua_iscfunction(lua_State* L, int idx);
+    int lua_isuserdata(lua_State* L, int idx);
+    int lua_type(lua_State* L, int idx);
+    const(char)* lua_typename(lua_State* L, int tp);
+    lua_Number lua_tonumberx(lua_State* L, int idx, int* isnum);
+    lua_Integer lua_tointegerx(lua_State* L, int idx, int* isnum);
+    lua_Unsigned lua_tounsignedx(lua_State* L, int idx, int* isnum);
+    int lua_toboolean(lua_State* L, int idx);
+    const(char)* lua_tolstring(lua_State* L, int idx, size_t* len);
+    size_t lua_rawlen(lua_State* L, int idx);
+    lua_CFunction lua_tocfunction(lua_State* L, int idx);
+    void* lua_touserdata(lua_State* L, int idx);
+    lua_State* lua_tothread(lua_State* L, int idx);
+    const(void)* lua_topointer(lua_State* L, int idx);
+    void lua_arith(lua_State* L, int op);
+    int lua_rawequal(lua_State* L, int idx1, int idx2);
+    int lua_compare(lua_State* L, int idx1, int idx2, int op);
+    void lua_pushnil(lua_State* L);
+    void lua_pushnumber(lua_State* L, lua_Number n);
+    void lua_pushinteger(lua_State* L, lua_Integer n);
+    void lua_pushunsigned(lua_State* L, lua_Unsigned n);
+    void lua_pushlstring(lua_State* L, const(char)* s, size_t l);
+    void lua_pushstring(lua_State* L, const(char)* s);
+    const(char)* lua_pushvfstring(lua_State* L, const(char)* fmt, va_list argp);
+    const(char)* lua_pushfstring(lua_State* L, const(char)* fmt, ...);
+    void lua_pushcclosure(lua_State* L, lua_CFunction fn, int n);
+    void lua_pushboolean(lua_State* L, int b);
+    void lua_pushlightuserdata(lua_State* L, void* p);
+    int lua_pushthread(lua_State* L);
+    void lua_getglobal(lua_State* L, const(char)* var);
+    void lua_gettable(lua_State* L, int idx);
+    void lua_getfield(lua_State* L, int idx, const(char)* k);
+    void lua_rawget(lua_State* L, int idx);
+    void lua_rawgeti(lua_State* L, int idx, int n);
+    void lua_rawgetp(lua_State* L, int idx, const(void)* p);
+    void lua_createtable(lua_State* L, int narr, int nrec);
+    void* lua_newuserdata(lua_State* L, size_t sz);
+    int lua_getmetatable(lua_State* L, int objindex);
+    void lua_getuservalue(lua_State* L, int idx);
+    void lua_setglobal(lua_State* L, const(char)* var);
+    void lua_settable(lua_State* L, int idx);
+    void lua_setfield(lua_State* L, int idx, const(char)* k);
+    void lua_rawset(lua_State* L, int idx);
+    void lua_rawseti(lua_State* L, int idx, int n);
+    void lua_rawsetp(lua_State* L, int idx, const(void)* p);
+    int lua_setmetatable(lua_State* L, int objindex);
+    int lua_setuservalue(lua_State* L, int idx);
+    void lua_callk(lua_State* L, int nargs, int nresults, int ctx, lua_CFunction k);
+    int lua_getctx(lua_State* L, int* ctx);
+    int lua_pcallk(lua_State* L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k);
+    int lua_load(lua_State* L, lua_Reader reader, void* dt, const(char)* chunkname, const(char)* mode);
+    int lua_dump(lua_State* L, lua_Writer writer, void* data);
+    int lua_yieldk(lua_State* L, int nresults, int ctx, lua_CFunction k);
+    int lua_resume(lua_State* L, lua_State* from, int narg);
+    int lua_status(lua_State* L);
+    int lua_gc(lua_State* L, int what, int data);
+    int lua_error(lua_State* L);
+    int lua_next(lua_State* L, int idx);
+    void lua_concat(lua_State* L, int n);
+    void lua_len(lua_State* L, int idx);
+    lua_Alloc lua_getallocf(lua_State* L, void** ud);
+    void lua_setallocf(lua_State* L, lua_Alloc f, void* ud);
+    int lua_getstack(lua_State* L, int level, lua_Debug* ar);
+    int lua_getinfo(lua_State* L, const(char)* what, lua_Debug* ar);
+    const(char)* lua_getlocal(lua_State* L, const(lua_Debug)* ar, int n);
+    const(char)* lua_setlocal(lua_State* L, const(lua_Debug)* ar, int n);
+    const(char)* lua_getupvalue(lua_State* L, int funcindex, int n);
+    const(char)* lua_setupvalue(lua_State* L, int funcindex, int n);
+    void* lua_upvalueid(lua_State* L, int fidx, int n);
+    void lua_upvaluejoin(lua_State* L, int fidx1, int n1, int fidx2, int n2);
+    int lua_sethook(lua_State* L, lua_Hook func, int mask, int count);
+    lua_Hook lua_gethook(lua_State* L);
+    int lua_gethookmask(lua_State* L);
+    int lua_gethookcount(lua_State* L);
+
+    // lualib.h
+    int luaopen_base(lua_State* L);
+    int luaopen_coroutine(lua_State* L);
+    int luaopen_table(lua_State* L);
+    int luaopen_io(lua_State* L);
+    int luaopen_os(lua_State* L);
+    int luaopen_string(lua_State* L);
+    int luaopen_bit32(lua_State* L);
+    int luaopen_math(lua_State* L);
+    int luaopen_debug(lua_State* L);
+    int luaopen_package(lua_State* L);
+    void luaL_openlibs(lua_State* L);

+ 261 - 0
source/bindbc/lua/v52/package.d

@@ -0,0 +1,261 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua.v52;
+
+version(LUA_52):
+
+public import bindbc.lua.v52.types;
+
+version(BindBC_Static) version = BindLua_Static;
+version(BindLua_Static) {
+    public import bindbc.lua.v52.bindstatic;
+}
+else public import bindbc.lua.v52.binddynamic;
+
+import core.stdc.config : c_long;
+
+// compatibility function aliases
+// luaconf.h
+alias lua_strlen = lua_rawlen;
+alias lua_objlen = lua_rawlen;
+
+// Macros
+@nogc nothrow {
+    // luaconf.h
+    int lua_equal(lua_State* L, int idx1, int idx2) {
+        pragma(inline, true)
+        return lua_compare(L, idx1, idx2, LUA_OPEQ);
+    }
+
+    int lua_lessthan(lua_State* L, int idx1, int idx2) {
+        pragma(inline, true)
+        return lua_compare(L, idx1, idx2, LUA_OPLT);
+    }
+
+    // lauxlib.h
+    void luaL_checkversion(lua_State* L) {
+        pragma(inline, true)
+        luaL_checkversion_(L, LUA_VERSION_NUM);
+    }
+
+    int luaL_loadfile(lua_State* L, const(char)* filename) {
+        pragma(inline, true)
+        return luaL_loadfilex(L, filename, null);
+    }
+
+    void luaL_newlibtable(lua_State* L, const(luaL_Reg)[] l) {
+        pragma(inline, true)
+        lua_createtable(L, 0, cast(int)l.length - 1);
+    }
+
+    void luaL_newlib(lua_State* L, const(luaL_Reg)[] l) {
+        pragma(inline, true)
+        luaL_newlibtable(L, l);
+        luaL_setfuncs(L, l.ptr, 0);
+    }
+
+    void luaL_argcheck(lua_State* L, bool cond, int arg, const(char)* extramsg) {
+        pragma(inline, true)
+        if(!cond) luaL_argerror(L, arg, extramsg);
+    }
+
+    const(char)* luaL_checkstring(lua_State* L, int arg) {
+        pragma(inline, true)
+        return luaL_checklstring(L, arg, null);
+    }
+
+    const(char)* luaL_optstring(lua_State* L, int arg, const(char)* d) {
+        pragma(inline, true)
+        return luaL_optlstring(L, arg, d, null);
+    }
+
+    int luaL_checkint(lua_State* L, int arg) {
+        pragma(inline, true)
+        return cast(int)luaL_checkinteger(L, arg);
+    }
+
+    int luaL_optint(lua_State* L, int arg, int d) {
+        pragma(inline, true)
+        return cast(int)luaL_optinteger(L, arg, d);
+    }
+
+    c_long luaL_checklong(lua_State* L, int arg) {
+        pragma(inline, true)
+        return cast(c_long)luaL_checkinteger(L, arg);
+    }
+
+    c_long luaL_optlong(lua_State* L, int arg, int d) {
+        pragma(inline, true)
+        return cast(c_long)luaL_optinteger(L, arg, d);
+    }
+
+    const(char)* luaL_typename(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_typename(L, lua_type(L, i));
+    }
+
+    bool luaL_dofile(lua_State* L, const(char)* filename) {
+        pragma(inline, true)
+        return luaL_loadfile(L, filename) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0;
+    }
+
+    bool luaL_dostring(lua_State* L, const(char)* str) {
+        pragma(inline, true)
+        return luaL_loadstring(L, str) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0;
+    }
+
+    void luaL_getmetatable(lua_State* L, const(char)* tname) {
+        pragma(inline, true)
+        lua_getfield(L, LUA_REGISTRYINDEX, tname);
+    }
+
+    // TODO: figure out what luaL_opt is supposed to do
+
+    int luaL_loadbuffer(lua_State *L, const(char)* buff, size_t sz, const(char)* name) {
+        pragma(inline, true)
+        return luaL_loadbufferx(L, buff, sz, name, null);
+    }
+
+    void luaL_addchar(luaL_Buffer* B, char c) {
+        pragma(inline, true)
+        if(B.n < B.size || luaL_prepbuffsize(B, 1)) {
+            B.b[B.n++] = c;
+        }
+    }
+
+    void luaL_addsize(luaL_Buffer* B, size_t s) {
+        pragma(inline, true)
+        B.n += s;
+    }
+
+    char* luaL_prepbuffer(luaL_Buffer* B) {
+        pragma(inline, true)
+        return luaL_prepbuffsize(B, LUAL_BUFFERSIZE);
+    }
+
+    // lua.h
+    int lua_upvalueindex(int i) {
+        pragma(inline, true)
+        return LUA_REGISTRYINDEX - i;
+    }
+
+    void lua_call(lua_State* L, int n, int r) {
+        pragma(inline, true)
+        lua_callk(L, n, r, 0, null);
+    }
+
+    int lua_pcall(lua_State* L, int n, int r, int f) {
+        pragma(inline, true)
+        return lua_pcallk(L, n, r, f, 0, null);
+    }
+
+    int lua_yield(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_yieldk(L, n, 0, null);
+    }
+
+    lua_Number lua_tonumber(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_tonumberx(L, i, null);
+    }
+
+    lua_Integer lua_tointeger(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_tointegerx(L, i, null);
+    }
+
+    lua_Unsigned lua_tounsigned(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_tounsignedx(L, i, null);
+    }
+
+    void lua_pop(lua_State* L, int n) {
+        pragma(inline, true)
+        lua_settop(L, -n - 1);
+    }
+
+    void lua_newtable(lua_State* L) {
+        pragma(inline, true)
+        lua_createtable(L, 0, 0);
+    }
+
+    void lua_register(lua_State* L, const(char)* n, lua_CFunction f) {
+        pragma(inline, true)
+        lua_pushcfunction(L, f);
+        lua_setglobal(L, n);
+    }
+
+    void lua_pushcfunction(lua_State* L, lua_CFunction f) {
+        pragma(inline, true)
+        lua_pushcclosure(L, f, 0);
+    }
+
+    bool lua_isfunction(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TFUNCTION;
+    }
+
+    bool lua_istable(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TTABLE;
+    }
+
+    bool lua_islightuserdata(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TLIGHTUSERDATA;
+    }
+
+    bool lua_isnil(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TNIL;
+    }
+
+    bool lua_isboolean(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TBOOLEAN;
+    }
+
+    bool lua_isthread(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TTHREAD;
+    }
+
+    bool lua_isnone(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TNONE;
+    }
+
+    bool lua_isnoneornil(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) <= 0;
+    }
+
+    void lua_pushliteral(lua_State* L, const(char)[] s) {
+        pragma(inline, true)
+        lua_pushlstring(L, s.ptr, s.length);
+    }
+
+    void lua_pushglobaltable(lua_State* L) {
+        pragma(inline, true)
+        lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
+    }
+
+    const(char)* lua_tostring(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_tolstring(L, i, null);
+    }
+
+    void lua_getregistry(lua_State* L) {
+        pragma(inline, true)
+        lua_pushvalue(L, LUA_REGISTRYINDEX);
+    }
+
+    int lua_getgccount(lua_State* L) {
+        pragma(inline, true)
+        return lua_gc(L, LUA_GCCOUNT, 0);
+    }
+}

+ 172 - 0
source/bindbc/lua/v52/types.d

@@ -0,0 +1,172 @@
+/+
++                Copyright 2023 Aya Partridge
++          Copyright 2019 - 2021 Michael D. Parker
++ Distributed under the Boost Software License, Version 1.0.
++     (See accompanying file LICENSE_1_0.txt or copy at
++           http://www.boost.org/LICENSE_1_0.txt)
++/
+module bindbc.lua.v52.types;
+
+version(LUA_52):
+
+import core.stdc.stdio: BUFSIZ, FILE;
+
+// luaconf.h
+enum LUA_IDSIZE = 60;
+alias LUA_INT32 = int;
+alias LUAI_UMEM = size_t;
+alias LUAI_MEM = ptrdiff_t;
+alias LUA_NUMBER = double;
+alias LUA_INTEGER = ptrdiff_t;
+alias LUA_UNSIGNED = uint;
+
+enum LUAL_BUFFERSIZE = BUFSIZ;
+
+enum LUAI_MAXSTACK = 1000000;
+
+enum LUAI_FIRSTPSEUDOIDX = (-LUAI_MAXSTACK - 1000);
+
+// lauxlib.h
+enum LUA_ERRFILE = LUA_ERRERR+1;
+
+struct luaL_Reg{
+	const(char)* name;
+	lua_CFunction func;
+}
+
+enum LUA_NOREF = -2;
+enum LUA_REFNIL = -1;
+
+struct luaL_Buffer{
+	char* b;
+	size_t size;
+	size_t n;
+	lua_State* L;
+	char[LUAL_BUFFERSIZE] buffer;
+}
+
+alias LUA_FILEHANDLE = FILE*;
+
+struct luaL_Stream{
+	FILE* f;
+	lua_CFunction closef;
+}
+
+// lua.h
+enum LUA_VERSION_MAJOR = "5";
+enum LUA_VERSION_MINOR = "2";
+enum LUA_VERSION_NUM = 502;
+enum LUA_VERSION_RELEASE = 4;
+
+enum LUA_VERSION = "Lua " ~ LUA_VERSION_MAJOR ~ "." ~ LUA_VERSION_MINOR;
+enum LUA_RELEASE = LUA_VERSION ~ "." ~ LUA_VERSION_RELEASE;
+
+enum LUA_SIGNATURE = "\033Lua";
+enum LUA_MULTRET = -1;
+
+enum LUA_REGISTRYINDEX = LUAI_FIRSTPSEUDOIDX;
+
+enum LUA_OK = 0;
+enum LUA_YIELD = 1;
+enum LUA_ERRRUN = 2;
+enum LUA_ERRSYNTAX = 3;
+enum LUA_ERRMEM = 4;
+enum LUA_ERRGCMM = 5;
+enum LUA_ERRERR = 6;
+
+struct lua_State;
+
+extern(C) nothrow{
+	alias lua_CFunction = int function(lua_State*);
+	alias lua_Reader = const(char)* function(lua_State*, void*, size_t*);
+	alias lua_Writer = int function(lua_State*, const(void)*, size_t, void*);
+	alias lua_Alloc = void* function(void*, void*, size_t, size_t);
+}
+
+enum LUA_TNONE = -1;
+enum LUA_TNIL = 0;
+enum LUA_TBOOLEAN = 1;
+enum LUA_TLIGHTUSERDATA = 2;
+enum LUA_TNUMBER = 3;
+enum LUA_TSTRING = 4;
+enum LUA_TTABLE = 5;
+enum LUA_TFUNCTION = 6;
+enum LUA_TUSERDATA = 7;
+enum LUA_TTHREAD = 8;
+enum LUA_NUMTAGS = 9;
+
+enum LUA_MINSTACK = 20;
+
+enum LUA_RIDX_MAINTHREAD = 1;
+enum LUA_RIDX_GLOBALS = 2;
+enum LUA_RIDX_LAST = LUA_RIDX_GLOBALS;
+
+alias lua_Number = LUA_NUMBER;
+alias lua_Integer = LUA_INTEGER;
+alias lua_Unsigned = LUA_UNSIGNED;
+
+enum LUA_OPADD = 0;
+enum LUA_OPSUB = 1;
+enum LUA_OPMUL = 2;
+enum LUA_OPDIV = 3;
+enum LUA_OPMOD = 4;
+enum LUA_OPPOW = 5;
+enum LUA_OPUNM = 6;
+
+enum LUA_OPEQ = 0;
+enum LUA_OPLT = 1;
+enum LUA_OPLE = 2;
+
+enum LUA_GCSTOP = 0;
+enum LUA_GCRESTART = 1;
+enum LUA_GCCOLLECT = 2;
+enum LUA_GCCOUNT = 3;
+enum LUA_GCCOUNTB = 4;
+enum LUA_GCSTEP = 5;
+enum LUA_GCSETPAUSE = 6;
+enum LUA_GCSETSTEPMUL = 7;
+enum LUA_GCSETMAJORINC = 8;
+enum LUA_GCISRUNNING = 9;
+enum LUA_GCGEN = 10;
+enum LUA_GCINC = 11;
+
+enum LUA_HOOKCALL = 0;
+enum LUA_HOOKRET = 1;
+enum LUA_HOOKLINE = 2;
+enum LUA_HOOKCOUNT = 3;
+enum LUA_HOOKTAILRET = 4;
+
+enum LUA_MASKCALL = 1 << LUA_HOOKCALL;
+enum LUA_MASKRET = 1 << LUA_HOOKRET;
+enum LUA_MASKLINE = 1 << LUA_HOOKLINE;
+enum LUA_MASKCOUNT = 1 << LUA_HOOKCOUNT;
+
+struct lua_Debug{
+	int event;
+	const(char)* name;
+	const(char)* namewhat;
+	const(char)* what;
+	const(char)* source;
+	int currentline;
+	int linedefined;
+	int lastlinedefined;
+	ubyte nups;
+	ubyte nparams;
+	char isvararg;
+	char istailcall;
+	char[LUA_IDSIZE] short_src;
+	private void* i_ci;
+}
+
+alias lua_Hook = extern(C) void function(lua_State*, lua_Debug*) nothrow;
+
+// lualib.h
+enum LUA_COLIBNAME = "coroutine";
+enum LUA_TABLIBNAME = "table";
+enum LUA_IOLIBNAME = "io";
+enum LUA_OSLIBNAME = "os";
+enum LUA_STRLIBNAME = "string";
+enum LUA_BITLIBNAME = "bit32";
+enum LUA_MATHLIBNAME = "math";
+enum LUA_DBLIBNAME = "debug";
+enum LUA_LOADLIBNAME = "package";

+ 533 - 0
source/bindbc/lua/v53/binddynamic.d

@@ -0,0 +1,533 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua.v53.binddynamic;
+
+version(BindBC_Static) version = BindLua_Static;
+version(BindLua_Static) {}
+else version = BindLua_Dynamic;
+
+version(LUA_53) {
+    version(BindLua_Dynamic) version = LUA_53_DYNAMIC;
+}
+
+version(LUA_53_DYNAMIC):
+
+import core.stdc.stdarg : va_list;
+import bindbc.loader;
+import bindbc.lua.config;
+import bindbc.lua.v53.types;
+
+extern(C) @nogc nothrow {
+    // lauxlib.h
+    alias pluaL_checkversion_ = void function(lua_State* L, lua_Number ver, size_t sz);
+    alias pluaL_getmetafield = int function(lua_State* L, int obj, const(char)* e);
+    alias pluaL_callmeta = int function(lua_State* L,  int obj, const(char)* e);
+    alias pluaL_tolstring = const(char)* function(lua_State* L, int idx, size_t* len);
+    alias pluaL_argerror = int function(lua_State* L, int arg, const(char)* extramsg);
+    alias pluaL_checklstring = const(char)* function(lua_State* L, int arg, size_t* l);
+    alias pluaL_optlstring = const(char)* function(lua_State* L, int arg, const(char)* def, size_t* l);
+    alias pluaL_checknumber = lua_Number function(lua_State* L, int arg);
+    alias pluaL_optnumber = lua_Number function(lua_State* L, int arg, lua_Number def);
+    alias pluaL_checkinteger = lua_Integer function(lua_State* L, int arg);
+    alias pluaL_optinteger = lua_Integer function(lua_State* L, int arg, lua_Integer def);
+    alias pluaL_checkstack = void function(lua_State* L, int sz, const(char)* msg);
+    alias pluaL_checktype = void function(lua_State* L, int arg, int t);
+    alias pluaL_checkany = void function(lua_State* L, int arg);
+    alias pluaL_newmetatable = int function(lua_State* L, const(char)* tname);
+    alias pluaL_setmetatable = void function(lua_State* L, const(char)* tname);
+    alias pluaL_testudata = void* function(lua_State* L, int ud, const(char)* tname);
+    alias pluaL_checkudata = void* function(lua_State* L, int id, const(char)* tname);
+    alias pluaL_where = void function(lua_State* L, int lvl);
+    alias pluaL_error = int function(lua_State* L, const(char)* fmt, ...);
+    alias pluaL_checkoption = int function(lua_State* L, int arg, const(char)* def, const(char)** lst);
+    alias pluaL_fileresult = int function(lua_State* L, int stat, const(char)* fname);
+    alias pluaL_execresult = int function(lua_State* L, int stat);
+    alias pluaL_ref = int function(lua_State* L, int t);
+    alias pluaL_unref = void function(lua_State* L, int t, int ref_);
+    alias pluaL_loadfilex = int function(lua_State* L, const(char)* filename, const(char)* mode);
+    alias pluaL_loadbufferx = int function(lua_State* L, const(char)* buff, size_t sz, const(char)* name, const(char)* mode);
+    alias pluaL_loadstring = int function(lua_State* L, const(char)* s);
+    alias pluaL_newstate = lua_State* function();
+    alias pluaL_len = int function(lua_State* L, int idx);
+    alias pluaL_gsub = const(char)* function(lua_State* L, const(char)* s, const(char)* p, const(char)* r);
+    alias pluaL_setfuncs = void function(lua_State* L, const(luaL_Reg)* l, int nup);
+    alias pluaL_getsubtable = int function(lua_State* L, int idx, const(char)* fname);
+    alias pluaL_traceback = void function(lua_State* L, lua_State* L1, const(char)* msg, int level);
+    alias pluaL_requiref = void function(lua_State* L, const(char)* modname, lua_CFunction openf, int glb);
+    alias pluaL_buffinit = void function(lua_State* L, luaL_Buffer* B);
+    alias pluaL_prepbuffsize = char* function(luaL_Buffer* B, size_t sz);
+    alias pluaL_addlstring = void function(luaL_Buffer* B, const(char)* s, size_t l);
+    alias pluaL_addstring = void function(luaL_Buffer* B,  const(char)* s);
+    alias pluaL_addvalue = void function(luaL_Buffer* B);
+    alias pluaL_pushresult = void function(luaL_Buffer* B);
+    alias pluaL_pushresultsize = void function(luaL_Buffer* B, size_t sz);
+    alias pluaL_buffinitsize = char* function(lua_State* L, luaL_Buffer*, size_t sz);
+
+    // lua.h
+    alias plua_newstate = lua_State* function(lua_Alloc f, void* ud);
+    alias plua_close = void function(lua_State* L);
+    alias plua_newthread = lua_State* function(lua_State* L);
+    alias plua_atpanic = lua_CFunction function(lua_State* L, lua_CFunction panicf);
+    alias plua_version = const(lua_Number)* function(lua_State* L);
+    alias plua_absindex = int function(lua_State* L, int idx);
+    alias plua_gettop = int function(lua_State* L);
+    alias plua_settop = void function(lua_State* L, int idx);
+    alias plua_pushvalue = void function(lua_State* L, int idx);
+    alias plua_rotate = void function(lua_State* L, int idx, int n);
+    alias plua_copy = void function(lua_State* L, int fromidx, int toidx);
+    alias plua_checkstack = int function(lua_State* L, int n);
+    alias plua_xmove = void function(lua_State* L, lua_State* to, int n);
+    alias plua_isnumber = int function(lua_State* L, int idx);
+    alias plua_isstring = int function(lua_State* L, int idx);
+    alias plua_iscfunction = int function(lua_State* L, int idx);
+    alias plua_isinteger = int function(lua_State* L, int idx);
+    alias plua_isuserdata = int function(lua_State* L, int idx);
+    alias plua_type = int function(lua_State* L, int idx);
+    alias plua_typename = const(char)* function(lua_State* L, int tp);
+    alias plua_tonumberx = lua_Number function(lua_State* L, int idx, int* isnum);
+    alias plua_tointegerx = lua_Integer function(lua_State* L, int idx, int* isnum);
+    alias plua_toboolean = int function(lua_State* L, int idx);
+    alias plua_tolstring = const(char)* function(lua_State* L, int idx, size_t* len);
+    alias plua_rawlen = size_t function(lua_State* L, int idx);
+    alias plua_tocfunction = lua_CFunction function(lua_State* L, int idx);
+    alias plua_touserdata = void* function(lua_State* L, int idx);
+    alias plua_tothread = lua_State* function(lua_State* L, int idx);
+    alias plua_topointer = const(void)* function(lua_State* L, int idx);
+    alias plua_arith = void function(lua_State* L, int op);
+    alias plua_rawequal = int function(lua_State* L, int idx1, int idx2);
+    alias plua_compare = int function(lua_State* L, int idx1, int idx2, int op);
+    alias plua_pushnil = void function(lua_State* L);
+    alias plua_pushnumber = void function(lua_State* L, lua_Number n);
+    alias plua_pushinteger = void function(lua_State* L, lua_Integer n);
+    alias plua_pushlstring = const(char)* function(lua_State* L, const(char)* s, size_t len);
+    alias plua_pushstring = const(char)* function(lua_State* L, const(char)* s);
+    alias plua_pushvfstring = const(char)* function(lua_State* L, const(char)* fmt, va_list argp);
+    alias plua_pushfstring = const(char)* function(lua_State* L, const(char)* fmt, ...);
+    alias plua_pushcclosure = void function(lua_State* L, lua_CFunction fn, int n);
+    alias plua_pushboolean = void function(lua_State* L, int b);
+    alias plua_pushlightuserdata = void function(lua_State* L, void* p);
+    alias plua_pushthread = int function(lua_State* L);
+    alias plua_getglobal = int function(lua_State* L, const(char)* name);
+    alias plua_gettable = int function(lua_State* L, int idx);
+    alias plua_getfield = int function(lua_State* L, int idx, const(char)* k);
+    alias plua_geti = int function(lua_State* L, int idx, lua_Integer n);
+    alias plua_rawget = int function(lua_State* L, int idx);
+    alias plua_rawgeti = int function(lua_State* L, int idx, int b);
+    alias plua_rawgetp = int function(lua_State* L, int idx, const(void)* p);
+    alias plua_createtable = void function(lua_State* L, int narr, int nrecs);
+    alias plua_newuserdata = void* function(lua_State* L, size_t sz);
+    alias plua_getmetatable = int function(lua_State* L, int objindex);
+    alias plua_getuservalue = int function(lua_State* L, int idx);
+    alias plua_setglobal = void function(lua_State* L, const(char)* name);
+    alias plua_settable = void function(lua_State* L, int idx);
+    alias plua_setfield = void function(lua_State* L, int idx, const(char)* k);
+    alias plua_seti = void function(lua_State* L, int idx, lua_Integer n);
+    alias plua_rawset = void function(lua_State* L, int idx);
+    alias plua_rawseti = void function(lua_State* L, int idx, lua_Integer n);
+    alias plua_rawsetp = void function(lua_State* L, int idx, const(void)* p);
+    alias plua_setmetatable = int function(lua_State* L, int objindex);
+    alias plua_setuservalue = int function(lua_State* L, int idx);
+    alias plua_callk = void function(lua_State* L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k);
+    alias plua_pcallk = int function(lua_State* L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k);
+    alias plua_load = int function(lua_State* L, lua_Reader reader, void* dt, const(char)* chunkname, const(char)* mode);
+    alias plua_dump = int function(lua_State* L, lua_Writer writer, void* data, int strip);
+    alias plua_yieldk = int function(lua_State* L, int nresults, lua_KContext ctx, lua_KFunction k);
+    alias plua_resume = int function(lua_State* L, lua_State* from, int narg);
+    alias plua_status = int function(lua_State* L);
+    alias plua_isyieldable = int function(lua_State* L);
+    alias plua_gc = int function(lua_State* L, int what, int data);
+    alias plua_error = int function(lua_State* L);
+    alias plua_next = int function(lua_State* L, int idx);
+    alias plua_concat = void function(lua_State* L, int n);
+    alias plua_len = void function(lua_State* L, int idx);
+    alias plua_stringtonumber = size_t function(lua_State* L, const(char)* s);
+    alias plua_getallocf = lua_Alloc function(lua_State* L, void** ud);
+    alias plua_setallocf = void function(lua_State* L, lua_Alloc f, void* ud);
+    alias plua_getstack = int function(lua_State* L, int, lua_Debug* ar);
+    alias plua_getinfo = int function(lua_State* L, const(char)* what, lua_Debug* ar);
+    alias plua_getlocal = const(char)* function(lua_State* L, const(lua_Debug)* ar, int n);
+    alias plua_setlocal = const(char)* function(lua_State* L, const(lua_Debug)* ar, int n);
+    alias plua_getupvalue = const(char)* function(lua_State* L, int funcindex, int n);
+    alias plua_setupvalue = const(char)* function(lua_State* L, int funcindex, int n);
+    alias plua_upvalueid = void* function(lua_State* L, int fidx,  int n);
+    alias plua_upvaluejoin = void function(lua_State* L, int fidx1,  int n1,  int fidx2,  int n2);
+    alias plua_sethook = int function(lua_State* L, lua_Hook func, int mask, int count);
+    alias plua_gethook = lua_Hook function(lua_State* L);
+    alias plua_gethookmask = int function(lua_State* L);
+    alias plua_gethookcount = int function(lua_State* L);
+
+    // lualib.h
+    alias pluaopen_base = int function(lua_State* L);
+    alias pluaopen_coroutine = int function(lua_State* L);
+    alias pluaopen_table = int function(lua_State* L);
+    alias pluaopen_io = int function(lua_State* L);
+    alias pluaopen_os = int function(lua_State* L);
+    alias pluaopen_string = int function(lua_State* L);
+    alias pluaopen_utf8 = int function(lua_State* L);
+    alias pluaopen_bit32 = int function(lua_State* L);
+    alias pluaopen_math = int function(lua_State* L);
+    alias pluaopen_debug = int function(lua_State* L);
+    alias pluaopen_package = int function(lua_State* L);
+    alias pluaL_openlibs = void function(lua_State* L);
+}
+
+__gshared {
+    // lauxlib.h
+    pluaL_checkversion_ luaL_checkversion_;
+    pluaL_getmetafield luaL_getmetafield;
+    pluaL_callmeta luaL_callmeta;
+    pluaL_tolstring luaL_tolstring;
+    pluaL_argerror luaL_argerror;
+    pluaL_checklstring luaL_checklstring;
+    pluaL_optlstring luaL_optlstring;
+    pluaL_checknumber luaL_checknumber;
+    pluaL_optnumber luaL_optnumber;
+    pluaL_checkinteger luaL_checkinteger;
+    pluaL_optinteger luaL_optinteger;
+    pluaL_checkstack luaL_checkstack;
+    pluaL_checktype luaL_checktype;
+    pluaL_checkany luaL_checkany;
+    pluaL_newmetatable luaL_newmetatable;
+    pluaL_setmetatable luaL_setmetatable;
+    pluaL_testudata luaL_testudata;
+    pluaL_checkudata luaL_checkudata;
+    pluaL_where luaL_where;
+    pluaL_error luaL_error;
+    pluaL_checkoption luaL_checkoption;
+    pluaL_fileresult luaL_fileresult;
+    pluaL_execresult luaL_execresult;
+    pluaL_ref luaL_ref;
+    pluaL_unref luaL_unref;
+    pluaL_loadfilex luaL_loadfilex;
+    pluaL_loadbufferx luaL_loadbufferx;
+    pluaL_loadstring luaL_loadstring;
+    pluaL_newstate luaL_newstate;
+    pluaL_len luaL_len;
+    pluaL_gsub luaL_gsub;
+    pluaL_setfuncs luaL_setfuncs;
+    pluaL_getsubtable luaL_getsubtable;
+    pluaL_traceback luaL_traceback;
+    pluaL_requiref luaL_requiref;
+    pluaL_buffinit luaL_buffinit;
+    pluaL_prepbuffsize luaL_prepbuffsize;
+    pluaL_addlstring luaL_addlstring;
+    pluaL_addstring luaL_addstring;
+    pluaL_addvalue luaL_addvalue;
+    pluaL_pushresult luaL_pushresult;
+    pluaL_pushresultsize luaL_pushresultsize;
+    pluaL_buffinitsize luaL_buffinitsize;
+
+    // lua.h
+    plua_newstate lua_newstate;
+    plua_close lua_close;
+    plua_newthread lua_newthread;
+    plua_atpanic lua_atpanic;
+    plua_version lua_version;
+    plua_absindex lua_absindex;
+    plua_gettop lua_gettop;
+    plua_settop lua_settop;
+    plua_pushvalue lua_pushvalue;
+    plua_rotate lua_rotate;
+    plua_copy lua_copy;
+    plua_checkstack lua_checkstack;
+    plua_xmove lua_xmove;
+    plua_isnumber lua_isnumber;
+    plua_isstring lua_isstring;
+    plua_iscfunction lua_iscfunction;
+    plua_isinteger lua_isinteger;
+    plua_isuserdata lua_isuserdata;
+    plua_type lua_type;
+    plua_typename lua_typename;
+    plua_tonumberx lua_tonumberx;
+    plua_tointegerx lua_tointegerx;
+    plua_toboolean lua_toboolean;
+    plua_tolstring lua_tolstring;
+    plua_rawlen lua_rawlen;
+    plua_tocfunction lua_tocfunction;
+    plua_touserdata lua_touserdata;
+    plua_tothread lua_tothread;
+    plua_topointer lua_topointer;
+    plua_arith lua_arith;
+    plua_rawequal lua_rawequal;
+    plua_compare lua_compare;
+    plua_pushnil lua_pushnil;
+    plua_pushnumber lua_pushnumber;
+    plua_pushinteger lua_pushinteger;
+    plua_pushlstring lua_pushlstring;
+    plua_pushstring lua_pushstring;
+    plua_pushvfstring lua_pushvfstring;
+    plua_pushfstring lua_pushfstring;
+    plua_pushcclosure lua_pushcclosure;
+    plua_pushboolean lua_pushboolean;
+    plua_pushlightuserdata lua_pushlightuserdata;
+    plua_pushthread lua_pushthread;
+    plua_getglobal lua_getglobal;
+    plua_gettable lua_gettable;
+    plua_getfield lua_getfield;
+    plua_geti lua_geti;
+    plua_rawget lua_rawget;
+    plua_rawgeti lua_rawgeti;
+    plua_rawgetp lua_rawgetp;
+    plua_createtable lua_createtable;
+    plua_newuserdata lua_newuserdata;
+    plua_getmetatable lua_getmetatable;
+    plua_getuservalue lua_getuservalue;
+    plua_setglobal lua_setglobal;
+    plua_settable lua_settable;
+    plua_setfield lua_setfield;
+    plua_seti lua_seti;
+    plua_rawset lua_rawset;
+    plua_rawseti lua_rawseti;
+    plua_rawsetp lua_rawsetp;
+    plua_setmetatable lua_setmetatable;
+    plua_setuservalue lua_setuservalue;
+    plua_callk lua_callk;
+    plua_pcallk lua_pcallk;
+    plua_load lua_load;
+    plua_dump lua_dump;
+    plua_yieldk lua_yieldk;
+    plua_resume lua_resume;
+    plua_status lua_status;
+    plua_isyieldable lua_isyieldable;
+    plua_gc lua_gc;
+    plua_error lua_error;
+    plua_next lua_next;
+    plua_concat lua_concat;
+    plua_len lua_len;
+    plua_stringtonumber lua_stringtonumber;
+    plua_getallocf lua_getallocf;
+    plua_setallocf lua_setallocf;
+    plua_getstack lua_getstack;
+    plua_getinfo lua_getinfo;
+    plua_getlocal lua_getlocal;
+    plua_setlocal lua_setlocal;
+    plua_getupvalue lua_getupvalue;
+    plua_setupvalue lua_setupvalue;
+    plua_upvalueid lua_upvalueid;
+    plua_upvaluejoin lua_upvaluejoin;
+    plua_sethook lua_sethook;
+    plua_gethook lua_gethook;
+    plua_gethookmask lua_gethookmask;
+    plua_gethookcount lua_gethookcount;
+
+    // lualib.h
+    pluaopen_base luaopen_base;
+    pluaopen_coroutine luaopen_coroutine;
+    pluaopen_table luaopen_table;
+    pluaopen_io luaopen_io;
+    pluaopen_os luaopen_os;
+    pluaopen_string luaopen_string;
+    pluaopen_utf8 luaopen_utf8;
+    pluaopen_bit32 luaopen_bit32;
+    pluaopen_math luaopen_math;
+    pluaopen_debug luaopen_debug;
+    pluaopen_package luaopen_package;
+    pluaL_openlibs luaL_openlibs;
+}
+
+private {
+    SharedLib lib;
+    LuaSupport loadedVersion;
+}
+
+@nogc nothrow:
+
+void unloadLua()
+{
+    if(lib != invalidHandle) {
+        lib.unload;
+    }
+}
+
+LuaSupport loadedLuaVersion() @safe { return loadedVersion; }
+bool isLuaLoaded() @safe { return lib != invalidHandle; }
+
+LuaSupport loadLua()
+{
+    version(Windows) {
+        const(char)[][3] libNames = ["lua5.3.dll", "lua53.dll", "lua5.3.5.dll"];
+    }
+    else version(OSX) {
+        const(char)[][1] libNames = "liblua.5.3.dylib";
+    }
+    else version(Posix) {
+        const(char)[][3] libNames = ["liblua.so.5.3", "liblua5.3.so", "liblua-5.3.so"];
+    }
+    else static assert(0, "bindbc-lua support for Lua 5.3 is not implemented on this platform.");
+
+    LuaSupport ret;
+    foreach(name; libNames) {
+        ret = loadLua(name.ptr);
+        if(ret != LuaSupport.noLibrary) break;
+    }
+    return ret;
+}
+
+LuaSupport loadLua(const(char)* libName)
+{
+    lib = load(libName);
+    if(lib == invalidHandle) {
+        return LuaSupport.noLibrary;
+    }
+
+    auto errCount = errorCount();
+    loadedVersion = LuaSupport.badLibrary;
+
+    // lauxlib.h
+    lib.bindSymbol(cast(void**)&luaL_checkversion_, "luaL_checkversion_");
+    lib.bindSymbol(cast(void**)&luaL_getmetafield,"luaL_getmetafield");
+    lib.bindSymbol(cast(void**)&luaL_callmeta, "luaL_callmeta");
+    lib.bindSymbol(cast(void**)&luaL_tolstring, "luaL_tolstring");
+    lib.bindSymbol(cast(void**)&luaL_argerror, "luaL_argerror");
+    lib.bindSymbol(cast(void**)&luaL_checklstring, "luaL_checklstring");
+    lib.bindSymbol(cast(void**)&luaL_optlstring, "luaL_optlstring");
+    lib.bindSymbol(cast(void**)&luaL_checknumber, "luaL_checknumber");
+    lib.bindSymbol(cast(void**)&luaL_optnumber, "luaL_optnumber");
+    lib.bindSymbol(cast(void**)&luaL_checkinteger, "luaL_checkinteger");
+    lib.bindSymbol(cast(void**)&luaL_optinteger, "luaL_optinteger");
+    lib.bindSymbol(cast(void**)&luaL_checkstack, "luaL_checkstack");
+    lib.bindSymbol(cast(void**)&luaL_checktype, "luaL_checktype");
+    lib.bindSymbol(cast(void**)&luaL_checkany, "luaL_checkany");
+    lib.bindSymbol(cast(void**)&luaL_newmetatable, "luaL_newmetatable");
+    lib.bindSymbol(cast(void**)&luaL_setmetatable, "luaL_setmetatable");
+    lib.bindSymbol(cast(void**)&luaL_testudata, "luaL_testudata");
+    lib.bindSymbol(cast(void**)&luaL_checkudata, "luaL_checkudata");
+    lib.bindSymbol(cast(void**)&luaL_where, "luaL_where");
+    lib.bindSymbol(cast(void**)&luaL_error, "luaL_error");
+    lib.bindSymbol(cast(void**)&luaL_checkoption, "luaL_checkoption");
+    lib.bindSymbol(cast(void**)&luaL_fileresult, "luaL_fileresult");
+    lib.bindSymbol(cast(void**)&luaL_execresult, "luaL_execresult");
+    lib.bindSymbol(cast(void**)&luaL_ref, "luaL_ref");
+    lib.bindSymbol(cast(void**)&luaL_unref, "luaL_unref");
+    lib.bindSymbol(cast(void**)&luaL_loadfilex, "luaL_loadfilex");
+    lib.bindSymbol(cast(void**)&luaL_loadbufferx, "luaL_loadbufferx");
+    lib.bindSymbol(cast(void**)&luaL_loadstring, "luaL_loadstring");
+    lib.bindSymbol(cast(void**)&luaL_newstate, "luaL_newstate");
+    lib.bindSymbol(cast(void**)&luaL_len, "luaL_len");
+    lib.bindSymbol(cast(void**)&luaL_gsub, "luaL_gsub");
+    lib.bindSymbol(cast(void**)&luaL_setfuncs, "luaL_setfuncs");
+    lib.bindSymbol(cast(void**)&luaL_getsubtable, "luaL_getsubtable");
+    lib.bindSymbol(cast(void**)&luaL_traceback, "luaL_traceback");
+    lib.bindSymbol(cast(void**)&luaL_requiref, "luaL_requiref");
+    lib.bindSymbol(cast(void**)&luaL_buffinit, "luaL_buffinit");
+    lib.bindSymbol(cast(void**)&luaL_prepbuffsize, "luaL_prepbuffsize");
+    lib.bindSymbol(cast(void**)&luaL_addlstring, "luaL_addlstring");
+    lib.bindSymbol(cast(void**)&luaL_addstring, "luaL_addstring");
+    lib.bindSymbol(cast(void**)&luaL_addvalue, "luaL_addvalue");
+    lib.bindSymbol(cast(void**)&luaL_pushresult, "luaL_pushresult");
+    lib.bindSymbol(cast(void**)&luaL_pushresultsize, "luaL_pushresultsize");
+    lib.bindSymbol(cast(void**)&luaL_buffinitsize, "luaL_buffinitsize");
+
+    // lua.h
+    lib.bindSymbol(cast(void**)&lua_newstate, "lua_newstate");
+    lib.bindSymbol(cast(void**)&lua_close, "lua_close");
+    lib.bindSymbol(cast(void**)&lua_newthread, "lua_newthread");
+    lib.bindSymbol(cast(void**)&lua_atpanic, "lua_atpanic");
+    lib.bindSymbol(cast(void**)&lua_version, "lua_version");
+    lib.bindSymbol(cast(void**)&lua_absindex, "lua_absindex");
+    lib.bindSymbol(cast(void**)&lua_gettop, "lua_gettop");
+    lib.bindSymbol(cast(void**)&lua_settop, "lua_settop");
+    lib.bindSymbol(cast(void**)&lua_pushvalue, "lua_pushvalue");
+    lib.bindSymbol(cast(void**)&lua_rotate, "lua_rotate");
+    lib.bindSymbol(cast(void**)&lua_copy, "lua_copy");
+    lib.bindSymbol(cast(void**)&lua_checkstack, "lua_checkstack");
+    lib.bindSymbol(cast(void**)&lua_xmove, "lua_xmove");
+    lib.bindSymbol(cast(void**)&lua_isnumber, "lua_isnumber");
+    lib.bindSymbol(cast(void**)&lua_isstring, "lua_isstring");
+    lib.bindSymbol(cast(void**)&lua_iscfunction, "lua_iscfunction");
+    lib.bindSymbol(cast(void**)&lua_isinteger, "lua_isinteger");
+    lib.bindSymbol(cast(void**)&lua_isuserdata, "lua_isuserdata");
+    lib.bindSymbol(cast(void**)&lua_type, "lua_type");
+    lib.bindSymbol(cast(void**)&lua_typename, "lua_typename");
+    lib.bindSymbol(cast(void**)&lua_tonumberx, "lua_tonumberx");
+    lib.bindSymbol(cast(void**)&lua_tointegerx, "lua_tointegerx");
+    lib.bindSymbol(cast(void**)&lua_toboolean, "lua_toboolean");
+    lib.bindSymbol(cast(void**)&lua_tolstring, "lua_tolstring");
+    lib.bindSymbol(cast(void**)&lua_rawlen, "lua_rawlen");
+    lib.bindSymbol(cast(void**)&lua_tocfunction, "lua_tocfunction");
+    lib.bindSymbol(cast(void**)&lua_touserdata, "lua_touserdata");
+    lib.bindSymbol(cast(void**)&lua_tothread, "lua_tothread");
+    lib.bindSymbol(cast(void**)&lua_topointer, "lua_topointer");
+    lib.bindSymbol(cast(void**)&lua_arith, "lua_arith");
+    lib.bindSymbol(cast(void**)&lua_rawequal, "lua_rawequal");
+    lib.bindSymbol(cast(void**)&lua_compare, "lua_compare");
+    lib.bindSymbol(cast(void**)&lua_pushnil, "lua_pushnil");
+    lib.bindSymbol(cast(void**)&lua_pushnumber, "lua_pushnumber");
+    lib.bindSymbol(cast(void**)&lua_pushinteger, "lua_pushinteger");
+    lib.bindSymbol(cast(void**)&lua_pushlstring, "lua_pushlstring");
+    lib.bindSymbol(cast(void**)&lua_pushstring, "lua_pushstring");
+    lib.bindSymbol(cast(void**)&lua_pushvfstring, "lua_pushvfstring");
+    lib.bindSymbol(cast(void**)&lua_pushfstring, "lua_pushfstring");
+    lib.bindSymbol(cast(void**)&lua_pushcclosure, "lua_pushcclosure");
+    lib.bindSymbol(cast(void**)&lua_pushboolean, "lua_pushboolean");
+    lib.bindSymbol(cast(void**)&lua_pushlightuserdata, "lua_pushlightuserdata");
+    lib.bindSymbol(cast(void**)&lua_pushthread, "lua_pushthread");
+    lib.bindSymbol(cast(void**)&lua_getglobal, "lua_getglobal");
+    lib.bindSymbol(cast(void**)&lua_gettable, "lua_gettable");
+    lib.bindSymbol(cast(void**)&lua_getfield, "lua_getfield");
+    lib.bindSymbol(cast(void**)&lua_geti, "lua_geti");
+    lib.bindSymbol(cast(void**)&lua_rawget, "lua_rawget");
+    lib.bindSymbol(cast(void**)&lua_rawgeti, "lua_rawgeti");
+    lib.bindSymbol(cast(void**)&lua_rawgetp, "lua_rawgetp");
+    lib.bindSymbol(cast(void**)&lua_createtable, "lua_createtable");
+    lib.bindSymbol(cast(void**)&lua_newuserdata, "lua_newuserdata");
+    lib.bindSymbol(cast(void**)&lua_getmetatable, "lua_getmetatable");
+    lib.bindSymbol(cast(void**)&lua_getuservalue, "lua_getuservalue");
+    lib.bindSymbol(cast(void**)&lua_setglobal, "lua_setglobal");
+    lib.bindSymbol(cast(void**)&lua_settable, "lua_settable");
+    lib.bindSymbol(cast(void**)&lua_setfield, "lua_setfield");
+    lib.bindSymbol(cast(void**)&lua_seti, "lua_seti");
+    lib.bindSymbol(cast(void**)&lua_rawset, "lua_rawset");
+    lib.bindSymbol(cast(void**)&lua_rawseti, "lua_rawseti");
+    lib.bindSymbol(cast(void**)&lua_rawsetp, "lua_rawsetp");
+    lib.bindSymbol(cast(void**)&lua_setmetatable, "lua_setmetatable");
+    lib.bindSymbol(cast(void**)&lua_setuservalue, "lua_setuservalue");
+    lib.bindSymbol(cast(void**)&lua_callk, "lua_callk");
+    lib.bindSymbol(cast(void**)&lua_pcallk, "lua_pcallk");
+    lib.bindSymbol(cast(void**)&lua_load, "lua_load");
+    lib.bindSymbol(cast(void**)&lua_dump, "lua_dump");
+    lib.bindSymbol(cast(void**)&lua_yieldk, "lua_yieldk");
+    lib.bindSymbol(cast(void**)&lua_resume, "lua_resume");
+    lib.bindSymbol(cast(void**)&lua_status, "lua_status");
+    lib.bindSymbol(cast(void**)&lua_isyieldable, "lua_isyieldable");
+    lib.bindSymbol(cast(void**)&lua_gc, "lua_gc");
+    lib.bindSymbol(cast(void**)&lua_error, "lua_error");
+    lib.bindSymbol(cast(void**)&lua_next, "lua_next");
+    lib.bindSymbol(cast(void**)&lua_concat, "lua_concat");
+    lib.bindSymbol(cast(void**)&lua_len, "lua_len");
+    lib.bindSymbol(cast(void**)&lua_stringtonumber, "lua_stringtonumber");
+    lib.bindSymbol(cast(void**)&lua_getallocf, "lua_getallocf");
+    lib.bindSymbol(cast(void**)&lua_setallocf, "lua_setallocf");
+    lib.bindSymbol(cast(void**)&lua_getstack, "lua_getstack");
+    lib.bindSymbol(cast(void**)&lua_getinfo, "lua_getinfo");
+    lib.bindSymbol(cast(void**)&lua_getlocal, "lua_getlocal");
+    lib.bindSymbol(cast(void**)&lua_setlocal, "lua_setlocal");
+    lib.bindSymbol(cast(void**)&lua_getupvalue, "lua_getupvalue");
+    lib.bindSymbol(cast(void**)&lua_setupvalue, "lua_setupvalue");
+    lib.bindSymbol(cast(void**)&lua_upvalueid, "lua_upvalueid");
+    lib.bindSymbol(cast(void**)&lua_upvaluejoin, "lua_upvaluejoin");
+    lib.bindSymbol(cast(void**)&lua_sethook, "lua_sethook");
+    lib.bindSymbol(cast(void**)&lua_gethook, "lua_gethook");
+    lib.bindSymbol(cast(void**)&lua_gethookmask, "lua_gethookmask");
+    lib.bindSymbol(cast(void**)&lua_gethookcount, "lua_gethookcount");
+
+    // lualib.h
+    lib.bindSymbol(cast(void**)&luaopen_base, "luaopen_base");
+    lib.bindSymbol(cast(void**)&luaopen_coroutine, "luaopen_coroutine");
+    lib.bindSymbol(cast(void**)&luaopen_table, "luaopen_table");
+    lib.bindSymbol(cast(void**)&luaopen_io, "luaopen_io");
+    lib.bindSymbol(cast(void**)&luaopen_os, "luaopen_os");
+    lib.bindSymbol(cast(void**)&luaopen_string, "luaopen_string");
+    lib.bindSymbol(cast(void**)&luaopen_utf8, "luaopen_utf8");
+    lib.bindSymbol(cast(void**)&luaopen_bit32, "luaopen_bit32");
+    lib.bindSymbol(cast(void**)&luaopen_math, "luaopen_math");
+    lib.bindSymbol(cast(void**)&luaopen_debug, "luaopen_debug");
+    lib.bindSymbol(cast(void**)&luaopen_package, "luaopen_package");
+    lib.bindSymbol(cast(void**)&luaL_openlibs, "luaL_openlibs");
+
+    return LuaSupport.lua53;
+}

+ 171 - 0
source/bindbc/lua/v53/bindstatic.d

@@ -0,0 +1,171 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua.v53.bindstatic;
+
+
+version(BindBC_Static) version = BindLua_Static;
+version(BindLua_Static) {
+    version(LUA_53) version = LUA_53_STATIC;
+}
+
+version(LUA_53_STATIC):
+
+import core.stdc.stdarg : va_list;
+import bindbc.lua.v53.types;
+
+extern(C) @nogc nothrow:
+    // lauxlib.h
+    void luaL_checkversion_(lua_State* L, lua_Number ver, size_t sz);
+    int luaL_getmetafield(lua_State* L, int obj, const(char)* e);
+    int luaL_callmeta(lua_State* L,  int obj, const(char)* e);
+    const(char)* luaL_tolstring(lua_State* L, int idx, size_t* len);
+    int luaL_argerror(lua_State* L, int arg, const(char)* extramsg);
+    const(char)* luaL_checklstring(lua_State* L, int arg, size_t* l);
+    const(char)* luaL_optlstring(lua_State* L, int arg, const(char)* def, size_t* l);
+    lua_Number luaL_checknumber(lua_State* L, int arg);
+    lua_Number luaL_optnumber(lua_State* L, int arg, lua_Number def);
+    lua_Integer luaL_checkinteger(lua_State* L, int arg);
+    lua_Integer luaL_optinteger(lua_State* L, int arg, lua_Integer def);
+    void luaL_checkstack(lua_State* L, int sz, const(char)* msg);
+    void luaL_checktype(lua_State* L, int arg, int t);
+    void luaL_checkany(lua_State* L, int arg);
+    int luaL_newmetatable(lua_State* L, const(char)* tname);
+    void luaL_setmetatable(lua_State* L, const(char)* tname);
+    void* luaL_testudata(lua_State* L, int ud, const(char)* tname);
+    void* luaL_checkudata(lua_State* L, int ud, const(char)* tname);
+    void luaL_where(lua_State* L, int lvl);
+    int luaL_error(lua_State* L, const(char)* fmt, ...);
+    int luaL_checkoption(lua_State* L, int arg, const(char)* def, const(char)** lst);
+    int luaL_fileresult(lua_State* L, int stat, const(char)* fname);
+    int luaL_execresult(lua_State* L, int stat);
+    int luaL_ref(lua_State* L, int t);
+    void luaL_unref(lua_State* L, int t, int ref_);
+    int luaL_loadfilex(lua_State* L, const(char)* filename, const(char)* mode);
+    int luaL_loadbufferx(lua_State* L, const(char)* buff, size_t sz, const(char)* name, const(char)* mode);
+    int luaL_loadstring(lua_State* L, const(char)* s);
+    lua_State* luaL_newstate();
+    int luaL_len(lua_State* L, int idx);
+    const(char)* luaL_gsub(lua_State* L, const(char)* s, const(char)* p, const(char)* r);
+    void luaL_setfuncs(lua_State* L, const(luaL_Reg)* l, int nup);
+    int luaL_getsubtable(lua_State* L, int idx, const(char)* fname);
+    void luaL_traceback(lua_State* L, lua_State* L1, const(char)* msg, int level);
+    void luaL_requiref(lua_State* L, const(char)* modname, lua_CFunction openf, int glb);
+    void luaL_buffinit(lua_State* L, luaL_Buffer* B);
+    char* luaL_prepbuffsize(luaL_Buffer* B, size_t sz);
+    void luaL_addlstring(luaL_Buffer* B, const(char)* s, size_t l);
+    void luaL_addstring(luaL_Buffer* B,  const(char)* s);
+    void luaL_addvalue(luaL_Buffer* B);
+    void luaL_pushresult(luaL_Buffer* B);
+    void luaL_pushresultsize(luaL_Buffer* B, size_t sz);
+    char* luaL_buffinitsize(lua_State* L, luaL_Buffer* B, size_t sz);
+
+    // lua.h
+    lua_State* lua_newstate(lua_Alloc f, void* ud);
+    lua_State* lua_close(lua_State* L);
+    lua_State* lua_newthread(lua_State* L);
+    lua_CFunction lua_atpanic(lua_State* L, lua_CFunction panicf);
+    const(lua_Number)* lua_version(lua_State* L);
+    int lua_absindex(lua_State* L, int idx);
+    int lua_gettop(lua_State* L);
+    void lua_settop(lua_State* L, int idx);
+    void lua_pushvalue(lua_State* L, int idx);
+    void lua_rotate(lua_State* L, int idx, int n);
+    void lua_copy(lua_State* L, int fromidx, int toidx);
+    int lua_checkstack(lua_State* L, int n);
+    void lua_xmove(lua_State* from, lua_State* to, int n);
+    int lua_isnumber(lua_State* L, int idx);
+    int lua_isstring(lua_State* L, int idx);
+    int lua_iscfunction(lua_State* L, int idx);
+    int lua_isinteger(lua_State* L, int idx);
+    int lua_isuserdata(lua_State* L, int idx);
+    int lua_type(lua_State* L, int idx);
+    const(char)* lua_typename(lua_State* L, int tp);
+    lua_Number lua_tonumberx(lua_State* L, int idx, int* isnum);
+    lua_Integer lua_tointegerx(lua_State* L, int idx, int* isnum);
+    int lua_toboolean(lua_State* L, int idx);
+    const(char)* lua_tolstring(lua_State* L, int idx, size_t* len);
+    size_t lua_rawlen(lua_State* L, int idx);
+    lua_CFunction lua_tocfunction(lua_State* L, int idx);
+    void* lua_touserdata(lua_State* L, int idx);
+    lua_State* lua_tothread(lua_State* L, int idx);
+    const(void)* lua_topointer(lua_State* L, int idx);
+    void lua_arith(lua_State* L, int op);
+    int lua_rawequal(lua_State* L, int idx1, int idx2);
+    int lua_compare(lua_State* L, int idx1, int idx2, int op);
+    void lua_pushnil(lua_State* L);
+    void lua_pushnumber(lua_State* L, lua_Number n);
+    void lua_pushinteger(lua_State* L, lua_Integer n);
+    void lua_pushlstring(lua_State* L, const(char)* s, size_t len);
+    void lua_pushstring(lua_State* L, const(char)* s);
+    const(char)* lua_pushvfstring(lua_State* L, const(char)* fmt, va_list argp);
+    const(char)* lua_pushfstring(lua_State* L, const(char)* fmt, ...);
+    void lua_pushcclosure(lua_State* L, lua_CFunction fn, int n);
+    void lua_pushboolean(lua_State* L, int b);
+    void lua_pushlightuserdata(lua_State* L, void* p);
+    int lua_pushthread(lua_State* L);
+    void lua_getglobal(lua_State* L, const(char)* name);
+    void lua_gettable(lua_State* L, int idx);
+    void lua_getfield(lua_State* L, int idx, const(char)* k);
+    int lua_geti(lua_State* L, int idx, lua_Integer n);
+    void lua_rawget(lua_State* L, int idx);
+    void lua_rawgeti(lua_State* L, int idx, int b);
+    void lua_rawgetp(lua_State* L, int idx, const(void)* p);
+    void lua_createtable(lua_State* L, int narr, int nrec);
+    void* lua_newuserdata(lua_State* L, size_t sz);
+    int lua_getmetatable(lua_State* L, int objindex);
+    void lua_getuservalue(lua_State* L, int idx);
+    void lua_setglobal(lua_State* L, const(char)* name);
+    void lua_settable(lua_State* L, int idx);
+    void lua_setfield(lua_State* L, int idx, const(char)* k);
+    void lua_seti(lua_State* L, int idx, lua_Integer n);
+    void lua_rawset(lua_State* L, int idx);
+    void lua_rawseti(lua_State* L, int idx, lua_Integer n);
+    void lua_rawsetp(lua_State* L, int idx, const(void)* p);
+    int lua_setmetatable(lua_State* L, int objindex);
+    int lua_setuservalue(lua_State* L, int idx);
+    void lua_callk(lua_State* L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k);
+    int lua_pcallk(lua_State* L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k);
+    int lua_load(lua_State* L, lua_Reader reader, void* dt, const(char)* chunkname, const(char)* mode);
+    int lua_dump(lua_State* L, lua_Writer writer, void* data, int strip);
+    int lua_yieldk(lua_State* L, int nresults, lua_KContext ctx, lua_KFunction k);
+    int lua_resume(lua_State* L, lua_State* from, int narg);
+    int lua_status(lua_State* L);
+    int lua_isyieldable(lua_State* L);
+    int lua_gc(lua_State* L, int what, int data);
+    int lua_error(lua_State* L);
+    int lua_next(lua_State* L, int idx);
+    void lua_concat(lua_State* L, int n);
+    void lua_len(lua_State* L, int idx);
+    size_t plua_stringtonumber(lua_State* L, const(char)* s);
+    lua_Alloc lua_getallocf(lua_State* L, void** ud);
+    void lua_setallocf(lua_State* L, lua_Alloc f, void* ud);
+    int lua_getstack(lua_State* L, int level, lua_Debug* ar);
+    int lua_getinfo(lua_State* L, const(char)* what, lua_Debug* ar);
+    const(char)* lua_getlocal(lua_State* L, const(lua_Debug)* ar, int n);
+    const(char)* lua_setlocal(lua_State* L, const(lua_Debug)* ar, int n);
+    const(char)* lua_getupvalue(lua_State* L, int funcindex, int n);
+    const(char)* lua_setupvalue(lua_State* L, int funcindex, int n);
+    void* lua_upvalueid(lua_State* L, int fidx, int n);
+    void lua_upvaluejoin(lua_State* L, int fidx1, int n1, int fidx2, int n2);
+    int lua_sethook(lua_State* L, lua_Hook func, int mask, int count);
+    lua_Hook lua_gethook(lua_State* L);
+    int lua_gethookmask(lua_State* L);
+    int lua_gethookcount(lua_State* L);
+
+    // lualib.h
+    int luaopen_base(lua_State* L);
+    int luaopen_coroutine(lua_State* L);
+    int luaopen_table(lua_State* L);
+    int luaopen_io(lua_State* L);
+    int luaopen_os(lua_State* L);
+    int luaopen_string(lua_State* L);
+    int luaopen_bit32(lua_State* L);
+    int luaopen_utf8(lua_State* L);
+    int luaopen_math(lua_State* L);
+    int luaopen_debug(lua_State* L);
+    int luaopen_package(lua_State* L);
+    void luaL_openlibs(lua_State* L);

+ 294 - 0
source/bindbc/lua/v53/package.d

@@ -0,0 +1,294 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua.v53;
+
+version(LUA_53):
+
+public import bindbc.lua.v53.types;
+
+version(BindBC_Static) version = BindLua_Static;
+version(BindLua_Static) {
+    public import bindbc.lua.v53.bindstatic;
+}
+else public import bindbc.lua.v53.binddynamic;
+
+import core.stdc.config : c_long;
+
+// compatibility function aliases
+// luaconf.h
+alias lua_strlen = lua_rawlen;
+alias lua_objlen = lua_rawlen;
+
+// Macros
+@nogc nothrow {
+    // luaconf.h
+    int lua_equal(lua_State* L, int idx1, int idx2) {
+        pragma(inline, true)
+        return lua_compare(L, idx1, idx2, LUA_OPEQ);
+    }
+
+    int lua_lessthan(lua_State* L, int idx1, int idx2) {
+        pragma(inline, true)
+        return lua_compare(L, idx1, idx2, LUA_OPLT);
+    }
+
+    // lauxlib.h
+    void luaL_checkversion(lua_State* L) {
+        pragma(inline, true)
+        luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES);
+    }
+
+    int luaL_loadfile(lua_State* L, const(char)* filename) {
+        pragma(inline, true)
+        return luaL_loadfilex(L, filename, null);
+    }
+
+    void luaL_newlibtable(lua_State* L, const(luaL_Reg)[] l) {
+        pragma(inline, true)
+        lua_createtable(L, 0, cast(int)l.length - 1);
+    }
+
+    void luaL_newlib(lua_State* L, const(luaL_Reg)[] l) {
+        pragma(inline, true)
+        luaL_newlibtable(L, l);
+        luaL_setfuncs(L, l.ptr, 0);
+    }
+
+    void luaL_argcheck(lua_State* L, bool cond, int arg, const(char)* extramsg) {
+        pragma(inline, true)
+        if(!cond) luaL_argerror(L, arg, extramsg);
+    }
+
+    const(char)* luaL_checkstring(lua_State* L, int arg) {
+        pragma(inline, true)
+        return luaL_checklstring(L, arg, null);
+    }
+
+    const(char)* luaL_optstring(lua_State* L, int arg, const(char)* d) {
+        pragma(inline, true)
+        return luaL_optlstring(L, arg, d, null);
+    }
+
+    const(char)* luaL_typename(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_typename(L, lua_type(L, i));
+    }
+
+    bool luaL_dofile(lua_State* L, const(char)* filename) {
+        pragma(inline, true)
+        return luaL_loadfile(L, filename) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0;
+    }
+
+    bool luaL_dostring(lua_State* L, const(char)* str) {
+        pragma(inline, true)
+        return luaL_loadstring(L, str) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0;
+    }
+
+    void luaL_getmetatable(lua_State* L, const(char)* tname) {
+        pragma(inline, true)
+        lua_getfield(L, LUA_REGISTRYINDEX, tname);
+    }
+
+    // TODO: figure out what luaL_opt is supposed to do
+
+    int luaL_loadbuffer(lua_State *L, const(char)* buff, size_t sz, const(char)* name) {
+        pragma(inline, true)
+        return luaL_loadbufferx(L, buff, sz, name, null);
+    }
+
+    void luaL_addchar(luaL_Buffer* B, char c) {
+        pragma(inline, true)
+        if(B.n < B.size || luaL_prepbuffsize(B, 1)) {
+            B.b[B.n++] = c;
+        }
+    }
+
+    void luaL_addsize(luaL_Buffer* B, size_t s) {
+        pragma(inline, true)
+        B.n += s;
+    }
+
+    char* luaL_prepbuffer(luaL_Buffer* B) {
+        pragma(inline, true)
+        return luaL_prepbuffsize(B, LUAL_BUFFERSIZE);
+    }
+
+    lua_Unsigned luaL_checkunsigned(lua_State* L, int a) {
+        pragma(inline, true)
+        return cast(lua_Unsigned)luaL_checkinteger(L, a);
+    }
+
+    lua_Unsigned luaL_optunsigned(lua_State* L, int a, lua_Unsigned d) {
+        pragma(inline, true)
+        return cast(lua_Unsigned)luaL_optinteger(L, a, d);
+    }
+
+    int luaL_checkint(lua_State* L, int a) {
+        pragma(inline, true)
+        return cast(int)luaL_checkinteger(L, a);
+    }
+
+    int luaL_optint(lua_State* L, int a, int d) {
+        pragma(inline, true)
+        return cast(int)luaL_optinteger(L, a, d);
+    }
+
+    c_long luaL_checklong(lua_State* L, int a) {
+        pragma(inline, true)
+        return cast(c_long)luaL_checkinteger(L, a);
+    }
+
+    c_long luaL_optlong(lua_State* L, int a, int d) {
+        pragma(inline, true)
+        return cast(c_long)luaL_optinteger(L, a, d);
+    }
+
+    // lua.h
+    int lua_upvalueindex(int i) {
+        pragma(inline, true)
+        return LUA_REGISTRYINDEX - i;
+    }
+
+    void lua_call(lua_State* L, int n, int r) {
+        pragma(inline, true)
+        lua_callk(L, n, r, 0, null);
+    }
+
+    int lua_pcall(lua_State* L, int n, int r, int f) {
+        pragma(inline, true)
+        return lua_pcallk(L, n, r, f, 0, null);
+    }
+
+    int lua_yield(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_yieldk(L, n, 0, null);
+    }
+
+    void* lua_getextraspace(lua_State* L) {
+        pragma(inline, true)
+        return cast(void*)((cast(char*)L) - LUA_EXTRASPACE);
+    }
+
+    lua_Number lua_tonumber(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_tonumberx(L, i, null);
+    }
+
+    lua_Integer lua_tointeger(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_tointegerx(L, i, null);
+    }
+
+    void lua_pop(lua_State* L, int n) {
+        pragma(inline, true)
+        lua_settop(L, -n - 1);
+    }
+
+    void lua_newtable(lua_State* L) {
+        pragma(inline, true)
+        lua_createtable(L, 0, 0);
+    }
+
+    void lua_register(lua_State* L, const(char)* n, lua_CFunction f) {
+        pragma(inline, true)
+        lua_pushcfunction(L, f);
+        lua_setglobal(L, n);
+    }
+
+    void lua_pushcfunction(lua_State* L, lua_CFunction f) {
+        pragma(inline, true)
+        lua_pushcclosure(L, f, 0);
+    }
+
+    bool lua_isfunction(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TFUNCTION;
+    }
+
+    bool lua_istable(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TTABLE;
+    }
+
+    bool lua_islightuserdata(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TLIGHTUSERDATA;
+    }
+
+    bool lua_isnil(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TNIL;
+    }
+
+    bool lua_isboolean(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TBOOLEAN;
+    }
+
+    bool lua_isthread(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TTHREAD;
+    }
+
+    bool lua_isnone(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TNONE;
+    }
+
+    bool lua_isnoneornil(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) <= 0;
+    }
+
+    void lua_pushliteral(lua_State* L, const(char)[] s) {
+        pragma(inline, true)
+        lua_pushlstring(L, s.ptr, s.length);
+    }
+
+    void lua_pushglobaltable(lua_State* L) {
+        pragma(inline, true)
+        lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
+    }
+
+    const(char)* lua_tostring(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_tolstring(L, i, null);
+    }
+
+    void lua_insert(lua_State* L, int idx) {
+        pragma(inline, true)
+        lua_rotate(L, idx, 1);
+    }
+
+    void lua_remove(lua_State* L, int idx) {
+        pragma(inline, true)
+        lua_rotate(L, idx, -1);
+        lua_pop(L, 1);
+    }
+
+    void lua_replace(lua_State* L, int idx) {
+        pragma(inline, true)
+        lua_copy(L, -1, idx);
+        lua_pop(L, 1);
+    }
+
+    void lua_pushunsigned(lua_State* L, lua_Unsigned n) {
+        pragma(inline, true)
+        lua_pushinteger(L, cast(lua_Integer)n);
+    }
+
+    lua_Unsigned lua_tounsignedx(lua_State* L, int i, int* pi) {
+        pragma(inline, true)
+        return cast(lua_Unsigned)lua_tointegerx(L, i, pi);
+    }
+
+    lua_Unsigned lua_tounsigned(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_tounsignedx(L, i, null);
+    }
+
+}

+ 184 - 0
source/bindbc/lua/v53/types.d

@@ -0,0 +1,184 @@
+/+
++                Copyright 2023 Aya Partridge
++          Copyright 2010 - 2021 Michael D. Parker
++ Distributed under the Boost Software License, Version 1.0.
++     (See accompanying file LICENSE_1_0.txt or copy at
++           http://www.boost.org/LICENSE_1_0.txt)
++/
+module bindbc.lua.v53.types;
+
+version(LUA_53):
+
+import core.stdc.stdio: BUFSIZ, FILE;
+import core.stdc.stdint: intptr_t;
+
+// luaconf.h
+alias LUA_INT32 = int;
+alias LUAI_UMEM = size_t;
+alias LUAI_MEM = ptrdiff_t;
+alias LUA_NUMBER = double;
+alias LUA_INTEGER = ptrdiff_t;
+alias LUA_UNSIGNED = uint;
+
+alias LUA_KCONTEXT =  intptr_t;
+enum LUAI_MAXSTACK = 1000000;
+enum LUA_EXTRASPACE = (void*).sizeof;
+enum LUA_IDSIZE = 60;
+enum LUAL_BUFFERSIZE = cast(int)(0x80 * (void*).sizeof * lua_Integer.sizeof);
+
+// lauxlib.h
+enum LUA_ERRFILE = LUA_ERRERR+1;
+enum LUA_LOADED_TABLE = "_LOADED";
+enum LUA_PRELOAD_TABLE = "_PRELOAD";
+
+struct luaL_Reg{
+	const(char)* name;
+	lua_CFunction func;
+}
+
+enum LUAL_NUMSIZES = lua_Integer.sizeof * 16 + lua_Number.sizeof;
+
+enum LUA_NOREF = -2;
+enum LUA_REFNIL = -1;
+
+struct luaL_Buffer{
+	char* b;
+	size_t size;
+	size_t n;
+	lua_State* L;
+	char[LUAL_BUFFERSIZE] initb;
+}
+
+alias LUA_FILEHANDLE = FILE*;
+
+struct luaL_Stream {
+	FILE* f;
+	lua_CFunction closef;
+}
+
+// lua.h
+enum LUA_VERSION_MAJOR = "5";
+enum LUA_VERSION_MINOR = "3";
+enum LUA_VERSION_NUM = 503;
+enum LUA_VERSION_RELEASE = 5;
+
+enum LUA_VERSION = "Lua " ~ LUA_VERSION_MAJOR ~ "." ~ LUA_VERSION_MINOR;
+enum LUA_RELEASE = LUA_VERSION ~ "." ~ LUA_VERSION_RELEASE;
+
+enum LUA_SIGNATURE = "\x1bLua";
+enum LUA_MULTRET = -1;
+
+enum LUA_REGISTRYINDEX = -LUAI_MAXSTACK - 1000;
+
+enum LUA_OK = 0;
+enum LUA_YIELD = 1;
+enum LUA_ERRRUN = 2;
+enum LUA_ERRSYNTAX = 3;
+enum LUA_ERRMEM = 4;
+enum LUA_ERRGCMM = 5;
+enum LUA_ERRERR = 6;
+
+struct lua_State;
+
+extern(C) nothrow{
+	alias lua_CFunction = int function(lua_State*);
+	alias lua_KFunction = int function(lua_State*, int, lua_KContext);
+	alias lua_Reader = const(char)* function(lua_State*, void*, size_t*);
+	alias lua_Writer = int function(lua_State*, const(void)*, size_t, void*);
+	alias lua_Alloc = void* function(void*, void*, size_t, size_t);
+}
+
+enum LUA_TNONE = -1;
+enum LUA_TNIL = 0;
+enum LUA_TBOOLEAN = 1;
+enum LUA_TLIGHTUSERDATA = 2;
+enum LUA_TNUMBER = 3;
+enum LUA_TSTRING = 4;
+enum LUA_TTABLE = 5;
+enum LUA_TFUNCTION = 6;
+enum LUA_TUSERDATA = 7;
+enum LUA_TTHREAD = 8;
+enum LUA_NUMTAGS = 9;
+
+enum LUA_MINSTACK = 20;
+
+enum LUA_RIDX_MAINTHREAD = 1;
+enum LUA_RIDX_GLOBALS = 2;
+enum LUA_RIDX_LAST = LUA_RIDX_GLOBALS;
+
+alias lua_Number = LUA_NUMBER;
+alias lua_Integer = LUA_INTEGER;
+alias lua_Unsigned = LUA_UNSIGNED;
+alias lua_KContext = LUA_KCONTEXT;
+
+enum LUA_OPADD = 0;
+enum LUA_OPSUB = 1;
+enum LUA_OPMUL = 2;
+enum LUA_OPMOD = 3;
+enum LUA_OPPOW = 4;
+enum LUA_OPDIV = 5;
+enum LUA_OPIDIV = 6;
+enum LUA_OPBAND = 7;
+enum LUA_OPBOR = 8;
+enum LUA_OPBXOR = 9;
+enum LUA_OPSHL = 10;
+enum LUA_OPSHR = 11;
+enum LUA_OPUNM = 12;
+enum LUA_OPBNOT = 13;
+
+enum LUA_OPEQ = 0;
+enum LUA_OPLT = 1;
+enum LUA_OPLE = 2;
+
+enum LUA_GCSTOP = 0;
+enum LUA_GCRESTART = 1;
+enum LUA_GCCOLLECT = 2;
+enum LUA_GCCOUNT = 3;
+enum LUA_GCCOUNTB = 4;
+enum LUA_GCSTEP = 5;
+enum LUA_GCSETPAUSE = 6;
+enum LUA_GCSETSTEPMUL = 7;
+enum LUA_GCISRUNNING = 9;
+
+enum LUA_HOOKCALL = 0;
+enum LUA_HOOKRET = 1;
+enum LUA_HOOKLINE = 2;
+enum LUA_HOOKCOUNT = 3;
+enum LUA_HOOKTAILRET = 4;
+
+enum LUA_MASKCALL = 1 << LUA_HOOKCALL;
+enum LUA_MASKRET = 1 << LUA_HOOKRET;
+enum LUA_MASKLINE = 1 << LUA_HOOKLINE;
+enum LUA_MASKCOUNT = 1 << LUA_HOOKCOUNT;
+
+struct lua_Debug{
+	int event;
+	const(char)* name;
+	const(char)* namewhat;
+	const(char)* what;
+	const(char)* source;
+	int currentline;
+	int linedefined;
+	int lastlinedefined;
+	ubyte nups;
+	ubyte nparams;
+	char isvararg;
+	char istailcall;
+	char[LUA_IDSIZE] short_src;
+	private void* i_ci;
+}
+
+alias lua_Hook = extern(C) void function(lua_State*, lua_Debug*) nothrow;
+
+// lualib.h
+enum LUA_VERSUFFIX = "_" ~ LUA_VERSION_MAJOR ~ "_" ~ LUA_VERSION_MINOR;
+enum LUA_COLIBNAME = "coroutine";
+enum LUA_TABLIBNAME = "table";
+enum LUA_IOLIBNAME = "io";
+enum LUA_OSLIBNAME = "os";
+enum LUA_STRLIBNAME = "string";
+enum LUA_UTF8LIBNAME = "utf8";
+enum LUA_BITLIBNAME = "bit32";
+enum LUA_MATHLIBNAME = "math";
+enum LUA_DBLIBNAME = "debug";
+enum LUA_LOADLIBNAME = "package";

+ 545 - 0
source/bindbc/lua/v54/binddynamic.d

@@ -0,0 +1,545 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua.v54.binddynamic;
+
+version(BindBC_Static) version = BindLua_Static;
+version(BindLua_Static) {}
+else version = BindLua_Dynamic;
+
+version(LUA_54) {
+    version(BindLua_Dynamic) version = LUA_54_DYNAMIC;
+}
+
+version(LUA_54_DYNAMIC):
+
+import core.stdc.stdarg : va_list;
+import bindbc.loader;
+import bindbc.lua.config;
+import bindbc.lua.v54.types;
+
+extern(C) @nogc nothrow {
+    // lauxlib.h
+    alias pluaL_checkversion_ = void function(lua_State* L, lua_Number ver, size_t sz);
+    alias pluaL_getmetafield = int function(lua_State* L, int obj, const(char)* e);
+    alias pluaL_callmeta = int function(lua_State* L,  int obj, const(char)* e);
+    alias pluaL_tolstring = const(char)* function(lua_State* L, int idx, size_t* len);
+    alias pluaL_argerror = int function(lua_State* L, int arg, const(char)* extramsg);
+    alias pluaL_typeerror = int function(lua_State *L, int arg, const(char)* tname);
+    alias pluaL_checklstring = const(char)* function(lua_State* L, int arg, size_t* l);
+    alias pluaL_optlstring = const(char)* function(lua_State* L, int arg, const(char)* def, size_t* l);
+    alias pluaL_checknumber = lua_Number function(lua_State* L, int arg);
+    alias pluaL_optnumber = lua_Number function(lua_State* L, int arg, lua_Number def);
+    alias pluaL_checkinteger = lua_Integer function(lua_State* L, int arg);
+    alias pluaL_optinteger = lua_Integer function(lua_State* L, int arg, lua_Integer def);
+    alias pluaL_checkstack = void function(lua_State* L, int sz, const(char)* msg);
+    alias pluaL_checktype = void function(lua_State* L, int arg, int t);
+    alias pluaL_checkany = void function(lua_State* L, int arg);
+    alias pluaL_newmetatable = int function(lua_State* L, const(char)* tname);
+    alias pluaL_setmetatable = void function(lua_State* L, const(char)* tname);
+    alias pluaL_testudata = void* function(lua_State* L, int ud, const(char)* tname);
+    alias pluaL_checkudata = void* function(lua_State* L, int id, const(char)* tname);
+    alias pluaL_where = void function(lua_State* L, int lvl);
+    alias pluaL_error = int function(lua_State* L, const(char)* fmt, ...);
+    alias pluaL_checkoption = int function(lua_State* L, int arg, const(char)* def, const(char)** lst);
+    alias pluaL_fileresult = int function(lua_State* L, int stat, const(char)* fname);
+    alias pluaL_execresult = int function(lua_State* L, int stat);
+    alias pluaL_ref = int function(lua_State* L, int t);
+    alias pluaL_unref = void function(lua_State* L, int t, int ref_);
+    alias pluaL_loadfilex = int function(lua_State* L, const(char)* filename, const(char)* mode);
+    alias pluaL_loadbufferx = int function(lua_State* L, const(char)* buff, size_t sz, const(char)* name, const(char)* mode);
+    alias pluaL_loadstring = int function(lua_State* L, const(char)* s);
+    alias pluaL_newstate = lua_State* function();
+    alias pluaL_len = int function(lua_State* L, int idx);
+    alias pluaL_addgsub = void function(luaL_Buffer *b, const(char)* s, const(char)* p, const(char)* r);
+    alias pluaL_gsub = const(char)* function(lua_State* L, const(char)* s, const(char)* p, const(char)* r);
+    alias pluaL_setfuncs = void function(lua_State* L, const(luaL_Reg)* l, int nup);
+    alias pluaL_getsubtable = int function(lua_State* L, int idx, const(char)* fname);
+    alias pluaL_traceback = void function(lua_State* L, lua_State* L1, const(char)* msg, int level);
+    alias pluaL_requiref = void function(lua_State* L, const(char)* modname, lua_CFunction openf, int glb);
+    alias pluaL_buffinit = void function(lua_State* L, luaL_Buffer* B);
+    alias pluaL_prepbuffsize = char* function(luaL_Buffer* B, size_t sz);
+    alias pluaL_addlstring = void function(luaL_Buffer* B, const(char)* s, size_t l);
+    alias pluaL_addstring = void function(luaL_Buffer* B,  const(char)* s);
+    alias pluaL_addvalue = void function(luaL_Buffer* B);
+    alias pluaL_pushresult = void function(luaL_Buffer* B);
+    alias pluaL_pushresultsize = void function(luaL_Buffer* B, size_t sz);
+    alias pluaL_buffinitsize = char* function(lua_State* L, luaL_Buffer*, size_t sz);
+
+    // lua.h
+    alias plua_newstate = lua_State* function(lua_Alloc f, void* ud);
+    alias plua_close = void function(lua_State* L);
+    alias plua_newthread = lua_State* function(lua_State* L);
+    alias plua_atpanic = lua_CFunction function(lua_State* L, lua_CFunction panicf);
+    alias plua_version = lua_Number function(lua_State* L);
+    alias plua_absindex = int function(lua_State* L, int idx);
+    alias plua_gettop = int function(lua_State* L);
+    alias plua_settop = void function(lua_State* L, int idx);
+    alias plua_pushvalue = void function(lua_State* L, int idx);
+    alias plua_rotate = void function(lua_State* L, int idx, int n);
+    alias plua_copy = void function(lua_State* L, int fromidx, int toidx);
+    alias plua_checkstack = int function(lua_State* L, int n);
+    alias plua_xmove = void function(lua_State* L, lua_State* to, int n);
+    alias plua_isnumber = int function(lua_State* L, int idx);
+    alias plua_isstring = int function(lua_State* L, int idx);
+    alias plua_iscfunction = int function(lua_State* L, int idx);
+    alias plua_isinteger = int function(lua_State* L, int idx);
+    alias plua_isuserdata = int function(lua_State* L, int idx);
+    alias plua_type = int function(lua_State* L, int idx);
+    alias plua_typename = const(char)* function(lua_State* L, int tp);
+    alias plua_tonumberx = lua_Number function(lua_State* L, int idx, int* isnum);
+    alias plua_tointegerx = lua_Integer function(lua_State* L, int idx, int* isnum);
+    alias plua_toboolean = int function(lua_State* L, int idx);
+    alias plua_tolstring = const(char)* function(lua_State* L, int idx, size_t* len);
+    alias plua_rawlen = lua_Unsigned function(lua_State* L, int idx);
+    alias plua_tocfunction = lua_CFunction function(lua_State* L, int idx);
+    alias plua_touserdata = void* function(lua_State* L, int idx);
+    alias plua_tothread = lua_State* function(lua_State* L, int idx);
+    alias plua_topointer = const(void)* function(lua_State* L, int idx);
+    alias plua_arith = void function(lua_State* L, int op);
+    alias plua_rawequal = int function(lua_State* L, int idx1, int idx2);
+    alias plua_compare = int function(lua_State* L, int idx1, int idx2, int op);
+    alias plua_pushnil = void function(lua_State* L);
+    alias plua_pushnumber = void function(lua_State* L, lua_Number n);
+    alias plua_pushinteger = void function(lua_State* L, lua_Integer n);
+    alias plua_pushlstring = const(char)* function(lua_State* L, const(char)* s, size_t len);
+    alias plua_pushstring = const(char)* function(lua_State* L, const(char)* s);
+    alias plua_pushvfstring = const(char)* function(lua_State* L, const(char)* fmt, va_list argp);
+    alias plua_pushfstring = const(char)* function(lua_State* L, const(char)* fmt, ...);
+    alias plua_pushcclosure = void function(lua_State* L, lua_CFunction fn, int n);
+    alias plua_pushboolean = void function(lua_State* L, int b);
+    alias plua_pushlightuserdata = void function(lua_State* L, void* p);
+    alias plua_pushthread = int function(lua_State* L);
+    alias plua_getglobal = int function(lua_State* L, const(char)* name);
+    alias plua_gettable = int function(lua_State* L, int idx);
+    alias plua_getfield = int function(lua_State* L, int idx, const(char)* k);
+    alias plua_geti = int function(lua_State* L, int idx, lua_Integer n);
+    alias plua_rawget = int function(lua_State* L, int idx);
+    alias plua_rawgeti = int function(lua_State* L, int idx, int b);
+    alias plua_rawgetp = int function(lua_State* L, int idx, const(void)* p);
+    alias plua_createtable = void function(lua_State* L, int narr, int nrecs);
+    alias plua_newuserdatauv = void* function(lua_State* L, size_t sz, int nuvalue);
+    alias plua_getmetatable = int function(lua_State* L, int objindex);
+    alias plua_getiuservalue = int function(lua_State* L, int idx, int n);
+    alias plua_setglobal = void function(lua_State* L, const(char)* name);
+    alias plua_settable = void function(lua_State* L, int idx);
+    alias plua_setfield = void function(lua_State* L, int idx, const(char)* k);
+    alias plua_seti = void function(lua_State* L, int idx, lua_Integer n);
+    alias plua_rawset = void function(lua_State* L, int idx);
+    alias plua_rawseti = void function(lua_State* L, int idx, lua_Integer n);
+    alias plua_rawsetp = void function(lua_State* L, int idx, const(void)* p);
+    alias plua_setmetatable = int function(lua_State* L, int objindex);
+    alias plua_setiuservalue = int function(lua_State* L, int idx, int n);
+    alias plua_callk = void function(lua_State* L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k);
+    alias plua_pcallk = int function(lua_State* L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k);
+    alias plua_load = int function(lua_State* L, lua_Reader reader, void* dt, const(char)* chunkname, const(char)* mode);
+    alias plua_dump = int function(lua_State* L, lua_Writer writer, void* data, int strip);
+    alias plua_yieldk = int function(lua_State* L, int nresults, lua_KContext ctx, lua_KFunction k);
+    alias plua_resume = int function(lua_State* L, lua_State* from, int narg, int* nres);
+    alias plua_status = int function(lua_State* L);
+    alias plua_isyieldable = int function(lua_State* L);
+    alias plua_setwarnf = void function(lua_State *L, lua_WarnFunction f, void *ud);
+    alias plua_warning = void function(lua_State *L, const char *msg, int tocont);
+    alias plua_gc = int function(lua_State* L, int what, ...);
+    alias plua_error = int function(lua_State* L);
+    alias plua_next = int function(lua_State* L, int idx);
+    alias plua_concat = void function(lua_State* L, int n);
+    alias plua_len = void function(lua_State* L, int idx);
+    alias plua_stringtonumber = size_t function(lua_State* L, const(char)* s);
+    alias plua_getallocf = lua_Alloc function(lua_State* L, void** ud);
+    alias plua_setallocf = void function(lua_State* L, lua_Alloc f, void* ud);
+    alias plua_toclose = void function(lua_State *L, int idx);
+    alias plua_getstack = int function(lua_State* L, int, lua_Debug* ar);
+    alias plua_getinfo = int function(lua_State* L, const(char)* what, lua_Debug* ar);
+    alias plua_getlocal = const(char)* function(lua_State* L, const(lua_Debug)* ar, int n);
+    alias plua_setlocal = const(char)* function(lua_State* L, const(lua_Debug)* ar, int n);
+    alias plua_getupvalue = const(char)* function(lua_State* L, int funcindex, int n);
+    alias plua_setupvalue = const(char)* function(lua_State* L, int funcindex, int n);
+    alias plua_upvalueid = void* function(lua_State* L, int fidx,  int n);
+    alias plua_upvaluejoin = void function(lua_State* L, int fidx1,  int n1,  int fidx2,  int n2);
+    alias plua_sethook = int function(lua_State* L, lua_Hook func, int mask, int count);
+    alias plua_gethook = lua_Hook function(lua_State* L);
+    alias plua_gethookmask = int function(lua_State* L);
+    alias plua_gethookcount = int function(lua_State* L);
+
+    // lualib.h
+    alias pluaopen_base = int function(lua_State* L);
+    alias pluaopen_coroutine = int function(lua_State* L);
+    alias pluaopen_table = int function(lua_State* L);
+    alias pluaopen_io = int function(lua_State* L);
+    alias pluaopen_os = int function(lua_State* L);
+    alias pluaopen_string = int function(lua_State* L);
+    alias pluaopen_utf8 = int function(lua_State* L);
+    alias pluaopen_math = int function(lua_State* L);
+    alias pluaopen_debug = int function(lua_State* L);
+    alias pluaopen_package = int function(lua_State* L);
+    alias pluaL_openlibs = void function(lua_State* L);
+}
+
+__gshared {
+    // lauxlib.h
+    pluaL_checkversion_ luaL_checkversion_;
+    pluaL_getmetafield luaL_getmetafield;
+    pluaL_callmeta luaL_callmeta;
+    pluaL_tolstring luaL_tolstring;
+    pluaL_argerror luaL_argerror;
+    pluaL_typeerror luaL_typeerror;
+    pluaL_checklstring luaL_checklstring;
+    pluaL_optlstring luaL_optlstring;
+    pluaL_checknumber luaL_checknumber;
+    pluaL_optnumber luaL_optnumber;
+    pluaL_checkinteger luaL_checkinteger;
+    pluaL_optinteger luaL_optinteger;
+    pluaL_checkstack luaL_checkstack;
+    pluaL_checktype luaL_checktype;
+    pluaL_checkany luaL_checkany;
+    pluaL_newmetatable luaL_newmetatable;
+    pluaL_setmetatable luaL_setmetatable;
+    pluaL_testudata luaL_testudata;
+    pluaL_checkudata luaL_checkudata;
+    pluaL_where luaL_where;
+    pluaL_error luaL_error;
+    pluaL_checkoption luaL_checkoption;
+    pluaL_fileresult luaL_fileresult;
+    pluaL_execresult luaL_execresult;
+    pluaL_ref luaL_ref;
+    pluaL_unref luaL_unref;
+    pluaL_loadfilex luaL_loadfilex;
+    pluaL_loadbufferx luaL_loadbufferx;
+    pluaL_loadstring luaL_loadstring;
+    pluaL_newstate luaL_newstate;
+    pluaL_len luaL_len;
+    pluaL_addgsub luaL_addgsub;
+    pluaL_gsub luaL_gsub;
+    pluaL_setfuncs luaL_setfuncs;
+    pluaL_getsubtable luaL_getsubtable;
+    pluaL_traceback luaL_traceback;
+    pluaL_requiref luaL_requiref;
+    pluaL_buffinit luaL_buffinit;
+    pluaL_prepbuffsize luaL_prepbuffsize;
+    pluaL_addlstring luaL_addlstring;
+    pluaL_addstring luaL_addstring;
+    pluaL_addvalue luaL_addvalue;
+    pluaL_pushresult luaL_pushresult;
+    pluaL_pushresultsize luaL_pushresultsize;
+    pluaL_buffinitsize luaL_buffinitsize;
+
+    // lua.h
+    plua_newstate lua_newstate;
+    plua_close lua_close;
+    plua_newthread lua_newthread;
+    plua_atpanic lua_atpanic;
+    plua_version lua_version;
+    plua_absindex lua_absindex;
+    plua_gettop lua_gettop;
+    plua_settop lua_settop;
+    plua_pushvalue lua_pushvalue;
+    plua_rotate lua_rotate;
+    plua_copy lua_copy;
+    plua_checkstack lua_checkstack;
+    plua_xmove lua_xmove;
+    plua_isnumber lua_isnumber;
+    plua_isstring lua_isstring;
+    plua_iscfunction lua_iscfunction;
+    plua_isinteger lua_isinteger;
+    plua_isuserdata lua_isuserdata;
+    plua_type lua_type;
+    plua_typename lua_typename;
+    plua_tonumberx lua_tonumberx;
+    plua_tointegerx lua_tointegerx;
+    plua_toboolean lua_toboolean;
+    plua_tolstring lua_tolstring;
+    plua_rawlen lua_rawlen;
+    plua_tocfunction lua_tocfunction;
+    plua_touserdata lua_touserdata;
+    plua_tothread lua_tothread;
+    plua_topointer lua_topointer;
+    plua_arith lua_arith;
+    plua_rawequal lua_rawequal;
+    plua_compare lua_compare;
+    plua_pushnil lua_pushnil;
+    plua_pushnumber lua_pushnumber;
+    plua_pushinteger lua_pushinteger;
+    plua_pushlstring lua_pushlstring;
+    plua_pushstring lua_pushstring;
+    plua_pushvfstring lua_pushvfstring;
+    plua_pushfstring lua_pushfstring;
+    plua_pushcclosure lua_pushcclosure;
+    plua_pushboolean lua_pushboolean;
+    plua_pushlightuserdata lua_pushlightuserdata;
+    plua_pushthread lua_pushthread;
+    plua_getglobal lua_getglobal;
+    plua_gettable lua_gettable;
+    plua_getfield lua_getfield;
+    plua_geti lua_geti;
+    plua_rawget lua_rawget;
+    plua_rawgeti lua_rawgeti;
+    plua_rawgetp lua_rawgetp;
+    plua_createtable lua_createtable;
+    plua_newuserdatauv lua_newuserdatauv;
+    plua_getmetatable lua_getmetatable;
+    plua_getiuservalue lua_getiuservalue;
+    plua_setglobal lua_setglobal;
+    plua_settable lua_settable;
+    plua_setfield lua_setfield;
+    plua_seti lua_seti;
+    plua_rawset lua_rawset;
+    plua_rawseti lua_rawseti;
+    plua_rawsetp lua_rawsetp;
+    plua_setmetatable lua_setmetatable;
+    plua_setiuservalue lua_setiuservalue;
+    plua_callk lua_callk;
+    plua_pcallk lua_pcallk;
+    plua_load lua_load;
+    plua_dump lua_dump;
+    plua_yieldk lua_yieldk;
+    plua_resume lua_resume;
+    plua_status lua_status;
+    plua_isyieldable lua_isyieldable;
+    plua_setwarnf lua_setwarnf;
+    plua_warning lua_warning;
+    plua_gc lua_gc;
+    plua_error lua_error;
+    plua_next lua_next;
+    plua_concat lua_concat;
+    plua_len lua_len;
+    plua_stringtonumber lua_stringtonumber;
+    plua_getallocf lua_getallocf;
+    plua_setallocf lua_setallocf;
+    plua_toclose lua_toclose;
+    plua_getstack lua_getstack;
+    plua_getinfo lua_getinfo;
+    plua_getlocal lua_getlocal;
+    plua_setlocal lua_setlocal;
+    plua_getupvalue lua_getupvalue;
+    plua_setupvalue lua_setupvalue;
+    plua_upvalueid lua_upvalueid;
+    plua_upvaluejoin lua_upvaluejoin;
+    plua_sethook lua_sethook;
+    plua_gethook lua_gethook;
+    plua_gethookmask lua_gethookmask;
+    plua_gethookcount lua_gethookcount;
+
+    // lualib.h
+    pluaopen_base luaopen_base;
+    pluaopen_coroutine luaopen_coroutine;
+    pluaopen_table luaopen_table;
+    pluaopen_io luaopen_io;
+    pluaopen_os luaopen_os;
+    pluaopen_string luaopen_string;
+    pluaopen_utf8 luaopen_utf8;
+    pluaopen_math luaopen_math;
+    pluaopen_debug luaopen_debug;
+    pluaopen_package luaopen_package;
+    pluaL_openlibs luaL_openlibs;
+}
+
+private {
+    SharedLib lib;
+    LuaSupport loadedVersion;
+}
+
+@nogc nothrow:
+
+void unloadLua()
+{
+    if(lib != invalidHandle) {
+        lib.unload;
+    }
+}
+
+LuaSupport loadedLuaVersion() @safe { return loadedVersion; }
+bool isLuaLoaded() @safe { return lib != invalidHandle; }
+
+LuaSupport loadLua()
+{
+    version(Windows) {
+        const(char)[][3] libNames = ["lua5.4.dll", "lua54.dll", "lua5.4.2.dll"];
+    }
+    else version(OSX) {
+        const(char)[][1] libNames = "liblua.5.4.dylib";
+    }
+    else version(Posix) {
+        const(char)[][3] libNames = ["liblua.so.5.4", "liblua5.4.so", "liblua-5.4.so"];
+    }
+    else static assert(0, "bindbc-lua support for Lua 5.4 is not implemented on this platform.");
+
+    LuaSupport ret;
+    foreach(name; libNames) {
+        ret = loadLua(name.ptr);
+        if(ret != LuaSupport.noLibrary) break;
+    }
+    return ret;
+}
+
+LuaSupport loadLua(const(char)* libName)
+{
+    lib = load(libName);
+    if(lib == invalidHandle) {
+        return LuaSupport.noLibrary;
+    }
+
+    auto errCount = errorCount();
+    loadedVersion = LuaSupport.badLibrary;
+
+    // lauxlib.h
+    lib.bindSymbol(cast(void**)&luaL_checkversion_, "luaL_checkversion_");
+    lib.bindSymbol(cast(void**)&luaL_getmetafield,"luaL_getmetafield");
+    lib.bindSymbol(cast(void**)&luaL_callmeta, "luaL_callmeta");
+    lib.bindSymbol(cast(void**)&luaL_tolstring, "luaL_tolstring");
+    lib.bindSymbol(cast(void**)&luaL_argerror, "luaL_argerror");
+    lib.bindSymbol(cast(void**)&luaL_typeerror, "luaL_typeerror");
+    lib.bindSymbol(cast(void**)&luaL_checklstring, "luaL_checklstring");
+    lib.bindSymbol(cast(void**)&luaL_optlstring, "luaL_optlstring");
+    lib.bindSymbol(cast(void**)&luaL_checknumber, "luaL_checknumber");
+    lib.bindSymbol(cast(void**)&luaL_optnumber, "luaL_optnumber");
+    lib.bindSymbol(cast(void**)&luaL_checkinteger, "luaL_checkinteger");
+    lib.bindSymbol(cast(void**)&luaL_optinteger, "luaL_optinteger");
+    lib.bindSymbol(cast(void**)&luaL_checkstack, "luaL_checkstack");
+    lib.bindSymbol(cast(void**)&luaL_checktype, "luaL_checktype");
+    lib.bindSymbol(cast(void**)&luaL_checkany, "luaL_checkany");
+    lib.bindSymbol(cast(void**)&luaL_newmetatable, "luaL_newmetatable");
+    lib.bindSymbol(cast(void**)&luaL_setmetatable, "luaL_setmetatable");
+    lib.bindSymbol(cast(void**)&luaL_testudata, "luaL_testudata");
+    lib.bindSymbol(cast(void**)&luaL_checkudata, "luaL_checkudata");
+    lib.bindSymbol(cast(void**)&luaL_where, "luaL_where");
+    lib.bindSymbol(cast(void**)&luaL_error, "luaL_error");
+    lib.bindSymbol(cast(void**)&luaL_checkoption, "luaL_checkoption");
+    lib.bindSymbol(cast(void**)&luaL_fileresult, "luaL_fileresult");
+    lib.bindSymbol(cast(void**)&luaL_execresult, "luaL_execresult");
+    lib.bindSymbol(cast(void**)&luaL_ref, "luaL_ref");
+    lib.bindSymbol(cast(void**)&luaL_unref, "luaL_unref");
+    lib.bindSymbol(cast(void**)&luaL_loadfilex, "luaL_loadfilex");
+    lib.bindSymbol(cast(void**)&luaL_loadbufferx, "luaL_loadbufferx");
+    lib.bindSymbol(cast(void**)&luaL_loadstring, "luaL_loadstring");
+    lib.bindSymbol(cast(void**)&luaL_newstate, "luaL_newstate");
+    lib.bindSymbol(cast(void**)&luaL_len, "luaL_len");
+    lib.bindSymbol(cast(void**)&luaL_addgsub, "luaL_addgsub");
+    lib.bindSymbol(cast(void**)&luaL_gsub, "luaL_gsub");
+    lib.bindSymbol(cast(void**)&luaL_setfuncs, "luaL_setfuncs");
+    lib.bindSymbol(cast(void**)&luaL_getsubtable, "luaL_getsubtable");
+    lib.bindSymbol(cast(void**)&luaL_traceback, "luaL_traceback");
+    lib.bindSymbol(cast(void**)&luaL_requiref, "luaL_requiref");
+    lib.bindSymbol(cast(void**)&luaL_buffinit, "luaL_buffinit");
+    lib.bindSymbol(cast(void**)&luaL_prepbuffsize, "luaL_prepbuffsize");
+    lib.bindSymbol(cast(void**)&luaL_addlstring, "luaL_addlstring");
+    lib.bindSymbol(cast(void**)&luaL_addstring, "luaL_addstring");
+    lib.bindSymbol(cast(void**)&luaL_addvalue, "luaL_addvalue");
+    lib.bindSymbol(cast(void**)&luaL_pushresult, "luaL_pushresult");
+    lib.bindSymbol(cast(void**)&luaL_pushresultsize, "luaL_pushresultsize");
+    lib.bindSymbol(cast(void**)&luaL_buffinitsize, "luaL_buffinitsize");
+
+    // lua.h
+    lib.bindSymbol(cast(void**)&lua_newstate, "lua_newstate");
+    lib.bindSymbol(cast(void**)&lua_close, "lua_close");
+    lib.bindSymbol(cast(void**)&lua_newthread, "lua_newthread");
+    lib.bindSymbol(cast(void**)&lua_atpanic, "lua_atpanic");
+    lib.bindSymbol(cast(void**)&lua_version, "lua_version");
+    lib.bindSymbol(cast(void**)&lua_absindex, "lua_absindex");
+    lib.bindSymbol(cast(void**)&lua_gettop, "lua_gettop");
+    lib.bindSymbol(cast(void**)&lua_settop, "lua_settop");
+    lib.bindSymbol(cast(void**)&lua_pushvalue, "lua_pushvalue");
+    lib.bindSymbol(cast(void**)&lua_rotate, "lua_rotate");
+    lib.bindSymbol(cast(void**)&lua_copy, "lua_copy");
+    lib.bindSymbol(cast(void**)&lua_checkstack, "lua_checkstack");
+    lib.bindSymbol(cast(void**)&lua_xmove, "lua_xmove");
+    lib.bindSymbol(cast(void**)&lua_isnumber, "lua_isnumber");
+    lib.bindSymbol(cast(void**)&lua_isstring, "lua_isstring");
+    lib.bindSymbol(cast(void**)&lua_iscfunction, "lua_iscfunction");
+    lib.bindSymbol(cast(void**)&lua_isinteger, "lua_isinteger");
+    lib.bindSymbol(cast(void**)&lua_isuserdata, "lua_isuserdata");
+    lib.bindSymbol(cast(void**)&lua_type, "lua_type");
+    lib.bindSymbol(cast(void**)&lua_typename, "lua_typename");
+    lib.bindSymbol(cast(void**)&lua_tonumberx, "lua_tonumberx");
+    lib.bindSymbol(cast(void**)&lua_tointegerx, "lua_tointegerx");
+    lib.bindSymbol(cast(void**)&lua_toboolean, "lua_toboolean");
+    lib.bindSymbol(cast(void**)&lua_tolstring, "lua_tolstring");
+    lib.bindSymbol(cast(void**)&lua_rawlen, "lua_rawlen");
+    lib.bindSymbol(cast(void**)&lua_tocfunction, "lua_tocfunction");
+    lib.bindSymbol(cast(void**)&lua_touserdata, "lua_touserdata");
+    lib.bindSymbol(cast(void**)&lua_tothread, "lua_tothread");
+    lib.bindSymbol(cast(void**)&lua_topointer, "lua_topointer");
+    lib.bindSymbol(cast(void**)&lua_arith, "lua_arith");
+    lib.bindSymbol(cast(void**)&lua_rawequal, "lua_rawequal");
+    lib.bindSymbol(cast(void**)&lua_compare, "lua_compare");
+    lib.bindSymbol(cast(void**)&lua_pushnil, "lua_pushnil");
+    lib.bindSymbol(cast(void**)&lua_pushnumber, "lua_pushnumber");
+    lib.bindSymbol(cast(void**)&lua_pushinteger, "lua_pushinteger");
+    lib.bindSymbol(cast(void**)&lua_pushlstring, "lua_pushlstring");
+    lib.bindSymbol(cast(void**)&lua_pushstring, "lua_pushstring");
+    lib.bindSymbol(cast(void**)&lua_pushvfstring, "lua_pushvfstring");
+    lib.bindSymbol(cast(void**)&lua_pushfstring, "lua_pushfstring");
+    lib.bindSymbol(cast(void**)&lua_pushcclosure, "lua_pushcclosure");
+    lib.bindSymbol(cast(void**)&lua_pushboolean, "lua_pushboolean");
+    lib.bindSymbol(cast(void**)&lua_pushlightuserdata, "lua_pushlightuserdata");
+    lib.bindSymbol(cast(void**)&lua_pushthread, "lua_pushthread");
+    lib.bindSymbol(cast(void**)&lua_getglobal, "lua_getglobal");
+    lib.bindSymbol(cast(void**)&lua_gettable, "lua_gettable");
+    lib.bindSymbol(cast(void**)&lua_getfield, "lua_getfield");
+    lib.bindSymbol(cast(void**)&lua_geti, "lua_geti");
+    lib.bindSymbol(cast(void**)&lua_rawget, "lua_rawget");
+    lib.bindSymbol(cast(void**)&lua_rawgeti, "lua_rawgeti");
+    lib.bindSymbol(cast(void**)&lua_rawgetp, "lua_rawgetp");
+    lib.bindSymbol(cast(void**)&lua_createtable, "lua_createtable");
+    lib.bindSymbol(cast(void**)&lua_newuserdatauv, "lua_newuserdatauv");
+    lib.bindSymbol(cast(void**)&lua_getmetatable, "lua_getmetatable");
+    lib.bindSymbol(cast(void**)&lua_getiuservalue, "lua_getiuservalue");
+    lib.bindSymbol(cast(void**)&lua_setglobal, "lua_setglobal");
+    lib.bindSymbol(cast(void**)&lua_settable, "lua_settable");
+    lib.bindSymbol(cast(void**)&lua_setfield, "lua_setfield");
+    lib.bindSymbol(cast(void**)&lua_seti, "lua_seti");
+    lib.bindSymbol(cast(void**)&lua_rawset, "lua_rawset");
+    lib.bindSymbol(cast(void**)&lua_rawseti, "lua_rawseti");
+    lib.bindSymbol(cast(void**)&lua_rawsetp, "lua_rawsetp");
+    lib.bindSymbol(cast(void**)&lua_setmetatable, "lua_setmetatable");
+    lib.bindSymbol(cast(void**)&lua_setiuservalue, "lua_setiuservalue");
+    lib.bindSymbol(cast(void**)&lua_callk, "lua_callk");
+    lib.bindSymbol(cast(void**)&lua_pcallk, "lua_pcallk");
+    lib.bindSymbol(cast(void**)&lua_load, "lua_load");
+    lib.bindSymbol(cast(void**)&lua_dump, "lua_dump");
+    lib.bindSymbol(cast(void**)&lua_yieldk, "lua_yieldk");
+    lib.bindSymbol(cast(void**)&lua_resume, "lua_resume");
+    lib.bindSymbol(cast(void**)&lua_status, "lua_status");
+    lib.bindSymbol(cast(void**)&lua_isyieldable, "lua_isyieldable");
+    lib.bindSymbol(cast(void**)&lua_setwarnf, "lua_setwarnf");
+    lib.bindSymbol(cast(void**)&lua_warning, "lua_warning");
+    lib.bindSymbol(cast(void**)&lua_gc, "lua_gc");
+    lib.bindSymbol(cast(void**)&lua_error, "lua_error");
+    lib.bindSymbol(cast(void**)&lua_next, "lua_next");
+    lib.bindSymbol(cast(void**)&lua_concat, "lua_concat");
+    lib.bindSymbol(cast(void**)&lua_len, "lua_len");
+    lib.bindSymbol(cast(void**)&lua_stringtonumber, "lua_stringtonumber");
+    lib.bindSymbol(cast(void**)&lua_getallocf, "lua_getallocf");
+    lib.bindSymbol(cast(void**)&lua_setallocf, "lua_setallocf");
+    lib.bindSymbol(cast(void**)&lua_toclose, "lua_toclose");
+    lib.bindSymbol(cast(void**)&lua_getstack, "lua_getstack");
+    lib.bindSymbol(cast(void**)&lua_getinfo, "lua_getinfo");
+    lib.bindSymbol(cast(void**)&lua_getlocal, "lua_getlocal");
+    lib.bindSymbol(cast(void**)&lua_setlocal, "lua_setlocal");
+    lib.bindSymbol(cast(void**)&lua_getupvalue, "lua_getupvalue");
+    lib.bindSymbol(cast(void**)&lua_setupvalue, "lua_setupvalue");
+    lib.bindSymbol(cast(void**)&lua_upvalueid, "lua_upvalueid");
+    lib.bindSymbol(cast(void**)&lua_upvaluejoin, "lua_upvaluejoin");
+    lib.bindSymbol(cast(void**)&lua_sethook, "lua_sethook");
+    lib.bindSymbol(cast(void**)&lua_gethook, "lua_gethook");
+    lib.bindSymbol(cast(void**)&lua_gethookmask, "lua_gethookmask");
+    lib.bindSymbol(cast(void**)&lua_gethookcount, "lua_gethookcount");
+
+    // lualib.h
+    lib.bindSymbol(cast(void**)&luaopen_base, "luaopen_base");
+    lib.bindSymbol(cast(void**)&luaopen_coroutine, "luaopen_coroutine");
+    lib.bindSymbol(cast(void**)&luaopen_table, "luaopen_table");
+    lib.bindSymbol(cast(void**)&luaopen_io, "luaopen_io");
+    lib.bindSymbol(cast(void**)&luaopen_os, "luaopen_os");
+    lib.bindSymbol(cast(void**)&luaopen_string, "luaopen_string");
+    lib.bindSymbol(cast(void**)&luaopen_utf8, "luaopen_utf8");
+    lib.bindSymbol(cast(void**)&luaopen_math, "luaopen_math");
+    lib.bindSymbol(cast(void**)&luaopen_debug, "luaopen_debug");
+    lib.bindSymbol(cast(void**)&luaopen_package, "luaopen_package");
+    lib.bindSymbol(cast(void**)&luaL_openlibs, "luaL_openlibs");
+
+    return LuaSupport.lua54;
+}

+ 175 - 0
source/bindbc/lua/v54/bindstatic.d

@@ -0,0 +1,175 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua.v54.bindstatic;
+
+
+version(BindBC_Static) version = BindLua_Static;
+version(BindLua_Static) {
+    version(LUA_54) version = LUA_54_STATIC;
+}
+
+version(LUA_54_STATIC):
+
+import core.stdc.stdarg : va_list;
+import bindbc.lua.v54.types;
+
+extern(C) @nogc nothrow:
+    // lauxlib.h
+    void luaL_checkversion_(lua_State* L, lua_Number ver, size_t sz);
+    int luaL_getmetafield(lua_State* L, int obj, const(char)* e);
+    int luaL_callmeta(lua_State* L,  int obj, const(char)* e);
+    const(char)* luaL_tolstring(lua_State* L, int idx, size_t* len);
+    int luaL_argerror(lua_State* L, int arg, const(char)* extramsg);
+    int luaL_typeerror(lua_State *L, int arg, const(char)* tname);
+    const(char)* luaL_checklstring(lua_State* L, int arg, size_t* l);
+    const(char)* luaL_optlstring(lua_State* L, int arg, const(char)* def, size_t* l);
+    lua_Number luaL_checknumber(lua_State* L, int arg);
+    lua_Number luaL_optnumber(lua_State* L, int arg, lua_Number def);
+    lua_Integer luaL_checkinteger(lua_State* L, int arg);
+    lua_Integer luaL_optinteger(lua_State* L, int arg, lua_Integer def);
+    void luaL_checkstack(lua_State* L, int sz, const(char)* msg);
+    void luaL_checktype(lua_State* L, int arg, int t);
+    void luaL_checkany(lua_State* L, int arg);
+    int luaL_newmetatable(lua_State* L, const(char)* tname);
+    void luaL_setmetatable(lua_State* L, const(char)* tname);
+    void* luaL_testudata(lua_State* L, int ud, const(char)* tname);
+    void* luaL_checkudata(lua_State* L, int ud, const(char)* tname);
+    void luaL_where(lua_State* L, int lvl);
+    int luaL_error(lua_State* L, const(char)* fmt, ...);
+    int luaL_checkoption(lua_State* L, int arg, const(char)* def, const(char)** lst);
+    int luaL_fileresult(lua_State* L, int stat, const(char)* fname);
+    int luaL_execresult(lua_State* L, int stat);
+    int luaL_ref(lua_State* L, int t);
+    void luaL_unref(lua_State* L, int t, int ref_);
+    int luaL_loadfilex(lua_State* L, const(char)* filename, const(char)* mode);
+    int luaL_loadbufferx(lua_State* L, const(char)* buff, size_t sz, const(char)* name, const(char)* mode);
+    int luaL_loadstring(lua_State* L, const(char)* s);
+    lua_State* luaL_newstate();
+    int luaL_len(lua_State* L, int idx);
+    void luaL_addgsub(luaL_Buffer *b, const(char)* s, const(char)* p, const(char)* r);
+    const(char)* luaL_gsub(lua_State* L, const(char)* s, const(char)* p, const(char)* r);
+    void luaL_setfuncs(lua_State* L, const(luaL_Reg)* l, int nup);
+    int luaL_getsubtable(lua_State* L, int idx, const(char)* fname);
+    void luaL_traceback(lua_State* L, lua_State* L1, const(char)* msg, int level);
+    void luaL_requiref(lua_State* L, const(char)* modname, lua_CFunction openf, int glb);
+    void luaL_buffinit(lua_State* L, luaL_Buffer* B);
+    char* luaL_prepbuffsize(luaL_Buffer* B, size_t sz);
+    void luaL_addlstring(luaL_Buffer* B, const(char)* s, size_t l);
+    void luaL_addstring(luaL_Buffer* B,  const(char)* s);
+    void luaL_addvalue(luaL_Buffer* B);
+    void luaL_pushresult(luaL_Buffer* B);
+    void luaL_pushresultsize(luaL_Buffer* B, size_t sz);
+    char* luaL_buffinitsize(lua_State* L, luaL_Buffer* B, size_t sz);
+
+    // lua.h
+    lua_State* lua_newstate(lua_Alloc f, void* ud);
+    lua_State* lua_close(lua_State* L);
+    lua_State* lua_newthread(lua_State* L);
+    lua_CFunction lua_atpanic(lua_State* L, lua_CFunction panicf);
+    lua_Number lua_version(lua_State* L);
+    int lua_absindex(lua_State* L, int idx);
+    int lua_gettop(lua_State* L);
+    void lua_settop(lua_State* L, int idx);
+    void lua_pushvalue(lua_State* L, int idx);
+    void lua_rotate(lua_State* L, int idx, int n);
+    void lua_copy(lua_State* L, int fromidx, int toidx);
+    int lua_checkstack(lua_State* L, int n);
+    void lua_xmove(lua_State* from, lua_State* to, int n);
+    int lua_isnumber(lua_State* L, int idx);
+    int lua_isstring(lua_State* L, int idx);
+    int lua_iscfunction(lua_State* L, int idx);
+    int lua_isinteger(lua_State* L, int idx);
+    int lua_isuserdata(lua_State* L, int idx);
+    int lua_type(lua_State* L, int idx);
+    const(char)* lua_typename(lua_State* L, int tp);
+    lua_Number lua_tonumberx(lua_State* L, int idx, int* isnum);
+    lua_Integer lua_tointegerx(lua_State* L, int idx, int* isnum);
+    int lua_toboolean(lua_State* L, int idx);
+    const(char)* lua_tolstring(lua_State* L, int idx, size_t* len);
+    lua_Unsigned lua_rawlen(lua_State* L, int idx);
+    lua_CFunction lua_tocfunction(lua_State* L, int idx);
+    void* lua_touserdata(lua_State* L, int idx);
+    lua_State* lua_tothread(lua_State* L, int idx);
+    const(void)* lua_topointer(lua_State* L, int idx);
+    void lua_arith(lua_State* L, int op);
+    int lua_rawequal(lua_State* L, int idx1, int idx2);
+    int lua_compare(lua_State* L, int idx1, int idx2, int op);
+    void lua_pushnil(lua_State* L);
+    void lua_pushnumber(lua_State* L, lua_Number n);
+    void lua_pushinteger(lua_State* L, lua_Integer n);
+    void lua_pushlstring(lua_State* L, const(char)* s, size_t len);
+    void lua_pushstring(lua_State* L, const(char)* s);
+    const(char)* lua_pushvfstring(lua_State* L, const(char)* fmt, va_list argp);
+    const(char)* lua_pushfstring(lua_State* L, const(char)* fmt, ...);
+    void lua_pushcclosure(lua_State* L, lua_CFunction fn, int n);
+    void lua_pushboolean(lua_State* L, int b);
+    void lua_pushlightuserdata(lua_State* L, void* p);
+    int lua_pushthread(lua_State* L);
+    void lua_getglobal(lua_State* L, const(char)* name);
+    void lua_gettable(lua_State* L, int idx);
+    void lua_getfield(lua_State* L, int idx, const(char)* k);
+    int lua_geti(lua_State* L, int idx, lua_Integer n);
+    void lua_rawget(lua_State* L, int idx);
+    void lua_rawgeti(lua_State* L, int idx, int b);
+    void lua_rawgetp(lua_State* L, int idx, const(void)* p);
+    void lua_createtable(lua_State* L, int narr, int nrec);
+    void* lua_newuserdatauv(lua_State* L, size_t sz, int nuvalue);
+    int lua_getmetatable(lua_State* L, int objindex);
+    int lua_getiuservalue(lua_State* L, int idx, int n);
+    void lua_setglobal(lua_State* L, const(char)* name);
+    void lua_settable(lua_State* L, int idx);
+    void lua_setfield(lua_State* L, int idx, const(char)* k);
+    void lua_seti(lua_State* L, int idx, lua_Integer n);
+    void lua_rawset(lua_State* L, int idx);
+    void lua_rawseti(lua_State* L, int idx, lua_Integer n);
+    void lua_rawsetp(lua_State* L, int idx, const(void)* p);
+    int lua_setmetatable(lua_State* L, int objindex);
+    int lua_setiuservalue(lua_State* L, int idx, int n);
+    void lua_callk(lua_State* L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k);
+    int lua_pcallk(lua_State* L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k);
+    int lua_load(lua_State* L, lua_Reader reader, void* dt, const(char)* chunkname, const(char)* mode);
+    int lua_dump(lua_State* L, lua_Writer writer, void* data, int strip);
+    int lua_yieldk(lua_State* L, int nresults, lua_KContext ctx, lua_KFunction k);
+    int lua_resume(lua_State* L, lua_State* from, int narg, int* nres);
+    int lua_status(lua_State* L);
+    int lua_isyieldable(lua_State* L);
+    void lua_setwarnf(lua_State *L, lua_WarnFunction f, void *ud);
+    void lua_warning(lua_State *L, const char *msg, int tocont);
+    int lua_gc(lua_State* L, int what, ...);
+    int lua_error(lua_State* L);
+    int lua_next(lua_State* L, int idx);
+    void lua_concat(lua_State* L, int n);
+    void lua_len(lua_State* L, int idx);
+    size_t plua_stringtonumber(lua_State* L, const(char)* s);
+    lua_Alloc lua_getallocf(lua_State* L, void** ud);
+    void lua_setallocf(lua_State* L, lua_Alloc f, void* ud);
+    void lua_toclose(lua_State *L, int idx);
+    int lua_getstack(lua_State* L, int level, lua_Debug* ar);
+    int lua_getinfo(lua_State* L, const(char)* what, lua_Debug* ar);
+    const(char)* lua_getlocal(lua_State* L, const(lua_Debug)* ar, int n);
+    const(char)* lua_setlocal(lua_State* L, const(lua_Debug)* ar, int n);
+    const(char)* lua_getupvalue(lua_State* L, int funcindex, int n);
+    const(char)* lua_setupvalue(lua_State* L, int funcindex, int n);
+    void* lua_upvalueid(lua_State* L, int fidx, int n);
+    void lua_upvaluejoin(lua_State* L, int fidx1, int n1, int fidx2, int n2);
+    int lua_sethook(lua_State* L, lua_Hook func, int mask, int count);
+    lua_Hook lua_gethook(lua_State* L);
+    int lua_gethookmask(lua_State* L);
+    int lua_gethookcount(lua_State* L);
+
+    // lualib.h
+    int luaopen_base(lua_State* L);
+    int luaopen_coroutine(lua_State* L);
+    int luaopen_table(lua_State* L);
+    int luaopen_io(lua_State* L);
+    int luaopen_os(lua_State* L);
+    int luaopen_string(lua_State* L);
+    int luaopen_utf8(lua_State* L);
+    int luaopen_math(lua_State* L);
+    int luaopen_debug(lua_State* L);
+    int luaopen_package(lua_State* L);
+    void luaL_openlibs(lua_State* L);

+ 330 - 0
source/bindbc/lua/v54/package.d

@@ -0,0 +1,330 @@
+
+//          Copyright 2019 - 2021 Michael D. Parker
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+module bindbc.lua.v54;
+
+version(LUA_54):
+
+public import bindbc.lua.v54.types;
+
+version(BindBC_Static) version = BindLua_Static;
+version(BindLua_Static) {
+    public import bindbc.lua.v54.bindstatic;
+}
+else public import bindbc.lua.v54.binddynamic;
+
+import core.stdc.config : c_long;
+
+// compatibility function aliases
+// luaconf.h
+alias lua_strlen = lua_rawlen;
+alias lua_objlen = lua_rawlen;
+
+// Macros
+@nogc nothrow {
+    // luaconf.h
+    int lua_equal(lua_State* L, int idx1, int idx2) {
+        pragma(inline, true)
+        return lua_compare(L, idx1, idx2, LUA_OPEQ);
+    }
+
+    int lua_lessthan(lua_State* L, int idx1, int idx2) {
+        pragma(inline, true)
+        return lua_compare(L, idx1, idx2, LUA_OPLT);
+    }
+
+    // lauxlib.h
+    void luaL_checkversion(lua_State* L) {
+        pragma(inline, true)
+        luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES);
+    }
+
+    int luaL_loadfile(lua_State* L, const(char)* filename) {
+        pragma(inline, true)
+        return luaL_loadfilex(L, filename, null);
+    }
+
+    void luaL_newlibtable(lua_State* L, const(luaL_Reg)[] l) {
+        pragma(inline, true)
+        lua_createtable(L, 0, cast(int)l.length - 1);
+    }
+
+    void luaL_newlib(lua_State* L, const(luaL_Reg)[] l) {
+        pragma(inline, true)
+        luaL_newlibtable(L, l);
+        luaL_setfuncs(L, l.ptr, 0);
+    }
+
+    void luaL_argcheck(lua_State* L, bool cond, int arg, const(char)* extramsg) {
+        pragma(inline, true)
+        if(!cond) luaL_argerror(L, arg, extramsg);
+    }
+
+    void luaL_argexpected(lua_State* L, bool cond, int arg, const(char)* tname) {
+        pragma(inline, true)
+        if(!cond) luaL_typeerror(L, arg, tname);
+    }
+
+    const(char)* luaL_checkstring(lua_State* L, int arg) {
+        pragma(inline, true)
+        return luaL_checklstring(L, arg, null);
+    }
+
+    const(char)* luaL_optstring(lua_State* L, int arg, const(char)* d) {
+        pragma(inline, true)
+        return luaL_optlstring(L, arg, d, null);
+    }
+
+    const(char)* luaL_typename(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_typename(L, lua_type(L, i));
+    }
+
+    bool luaL_dofile(lua_State* L, const(char)* filename) {
+        pragma(inline, true)
+        return luaL_loadfile(L, filename) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0;
+    }
+
+    bool luaL_dostring(lua_State* L, const(char)* str) {
+        pragma(inline, true)
+        return luaL_loadstring(L, str) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0;
+    }
+
+    void luaL_getmetatable(lua_State* L, const(char)* tname) {
+        pragma(inline, true)
+        lua_getfield(L, LUA_REGISTRYINDEX, tname);
+    }
+
+    // TODO: figure out what luaL_opt is supposed to do
+
+    int luaL_loadbuffer(lua_State *L, const(char)* buff, size_t sz, const(char)* name) {
+        pragma(inline, true)
+        return luaL_loadbufferx(L, buff, sz, name, null);
+    }
+
+    alias luaL_pushfail = lua_pushnil;
+
+    size_t luaL_bufflen(luaL_Buffer* B) {
+        pragma(inline, true)
+        return B.n;
+    }
+
+    char* luaL_buffaddr(luaL_Buffer* B) {
+        pragma(inline, true)
+        return B.b;
+    }
+
+    void luaL_addchar(luaL_Buffer* B, char c) {
+        pragma(inline, true)
+        if(B.n < B.size || luaL_prepbuffsize(B, 1)) {
+            B.b[B.n++] = c;
+        }
+    }
+
+    void luaL_addsize(luaL_Buffer* B, size_t s) {
+        pragma(inline, true)
+        B.n += s;
+    }
+
+    void luaL_buffsub(luaL_Buffer* B, size_t s) {
+        pragma(inline, true)
+        B.n -= s;
+    }
+
+    char* luaL_prepbuffer(luaL_Buffer* B) {
+        pragma(inline, true)
+        return luaL_prepbuffsize(B, LUAL_BUFFERSIZE);
+    }
+
+    lua_Unsigned luaL_checkunsigned(lua_State* L, int a) {
+        pragma(inline, true)
+        return cast(lua_Unsigned)luaL_checkinteger(L, a);
+    }
+
+    lua_Unsigned luaL_optunsigned(lua_State* L, int a, lua_Unsigned d) {
+        pragma(inline, true)
+        return cast(lua_Unsigned)luaL_optinteger(L, a, d);
+    }
+
+    int luaL_checkint(lua_State* L, int a) {
+        pragma(inline, true)
+        return cast(int)luaL_checkinteger(L, a);
+    }
+
+    int luaL_optint(lua_State* L, int a, int d) {
+        pragma(inline, true)
+        return cast(int)luaL_optinteger(L, a, d);
+    }
+
+    c_long luaL_checklong(lua_State* L, int a) {
+        pragma(inline, true)
+        return cast(c_long)luaL_checkinteger(L, a);
+    }
+
+    c_long luaL_optlong(lua_State* L, int a, int d) {
+        pragma(inline, true)
+        return cast(c_long)luaL_optinteger(L, a, d);
+    }
+
+    // lua.h
+    int lua_upvalueindex(int i) {
+        pragma(inline, true)
+        return LUA_REGISTRYINDEX - i;
+    }
+
+    void lua_call(lua_State* L, int n, int r) {
+        pragma(inline, true)
+        lua_callk(L, n, r, 0, null);
+    }
+
+    int lua_pcall(lua_State* L, int n, int r, int f) {
+        pragma(inline, true)
+        return lua_pcallk(L, n, r, f, 0, null);
+    }
+
+    int lua_yield(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_yieldk(L, n, 0, null);
+    }
+
+    void* lua_getextraspace(lua_State* L) {
+        pragma(inline, true)
+        return cast(void*)((cast(char*)L) - LUA_EXTRASPACE);
+    }
+
+    lua_Number lua_tonumber(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_tonumberx(L, i, null);
+    }
+
+    lua_Integer lua_tointeger(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_tointegerx(L, i, null);
+    }
+
+    void lua_pop(lua_State* L, int n) {
+        pragma(inline, true)
+        lua_settop(L, -n - 1);
+    }
+
+    void lua_newtable(lua_State* L) {
+        pragma(inline, true)
+        lua_createtable(L, 0, 0);
+    }
+
+    void lua_register(lua_State* L, const(char)* n, lua_CFunction f) {
+        pragma(inline, true)
+        lua_pushcfunction(L, f);
+        lua_setglobal(L, n);
+    }
+
+    void lua_pushcfunction(lua_State* L, lua_CFunction f) {
+        pragma(inline, true)
+        lua_pushcclosure(L, f, 0);
+    }
+
+    bool lua_isfunction(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TFUNCTION;
+    }
+
+    bool lua_istable(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TTABLE;
+    }
+
+    bool lua_islightuserdata(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TLIGHTUSERDATA;
+    }
+
+    bool lua_isnil(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TNIL;
+    }
+
+    bool lua_isboolean(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TBOOLEAN;
+    }
+
+    bool lua_isthread(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TTHREAD;
+    }
+
+    bool lua_isnone(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) == LUA_TNONE;
+    }
+
+    bool lua_isnoneornil(lua_State* L, int n) {
+        pragma(inline, true)
+        return lua_type(L, n) <= 0;
+    }
+
+    void lua_pushliteral(lua_State* L, const(char)[] s) {
+        pragma(inline, true)
+        lua_pushlstring(L, s.ptr, s.length);
+    }
+
+    void lua_pushglobaltable(lua_State* L) {
+        pragma(inline, true)
+        lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
+    }
+
+    const(char)* lua_tostring(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_tolstring(L, i, null);
+    }
+
+    void lua_insert(lua_State* L, int idx) {
+        pragma(inline, true)
+        lua_rotate(L, idx, 1);
+    }
+
+    void lua_remove(lua_State* L, int idx) {
+        pragma(inline, true)
+        lua_rotate(L, idx, -1);
+        lua_pop(L, 1);
+    }
+
+    void lua_replace(lua_State* L, int idx) {
+        pragma(inline, true)
+        lua_copy(L, -1, idx);
+        lua_pop(L, 1);
+    }
+
+    void lua_pushunsigned(lua_State* L, lua_Unsigned n) {
+        pragma(inline, true)
+        lua_pushinteger(L, cast(lua_Integer)n);
+    }
+
+    lua_Unsigned lua_tounsignedx(lua_State* L, int i, int* pi) {
+        pragma(inline, true)
+        return cast(lua_Unsigned)lua_tointegerx(L, i, pi);
+    }
+
+    lua_Unsigned lua_tounsigned(lua_State* L, int i) {
+        pragma(inline, true)
+        return lua_tounsignedx(L, i, null);
+    }
+
+    void* lua_newuserdata(lua_State* L, size_t s) {
+        pragma(inline, true)
+        return lua_newuserdatauv(L, s, 1);
+    }
+
+    int lua_getuservalue(lua_State* L, int idx) {
+        pragma(inline, true)
+        return lua_getiuservalue(L, idx, 1);
+    }
+
+    int lua_setuservalue(lua_State* L, int idx) {
+        pragma(inline, true)
+        return lua_setiuservalue(L, idx, 1);
+    }
+}

+ 203 - 0
source/bindbc/lua/v54/types.d

@@ -0,0 +1,203 @@
+/+
++                Copyright 2023 Aya Partridge
++          Copyright 2019 - 2021 Michael D. Parker
++ Distributed under the Boost Software License, Version 1.0.
++     (See accompanying file LICENSE_1_0.txt or copy at
++           http://www.boost.org/LICENSE_1_0.txt)
++/
+module bindbc.lua.v54.types;
+
+version(LUA_54):
+
+import core.stdc.stdio: BUFSIZ, FILE;
+import core.stdc.stdint: intptr_t;
+import core.stdc.config: c_long;
+
+// luaconf.h
+alias LUA_INT32 = int;
+alias LUAI_UMEM = size_t;
+alias LUAI_MEM = ptrdiff_t;
+alias LUA_NUMBER = double;
+alias LUA_INTEGER = ptrdiff_t;
+alias LUA_UNSIGNED = uint;
+
+alias LUA_KCONTEXT =  intptr_t;
+enum LUAI_MAXSTACK = 1000000;
+enum LUA_EXTRASPACE = (void*).sizeof;
+enum LUA_IDSIZE = 60;
+enum LUAL_BUFFERSIZE = cast(int)(16 * (void*).sizeof * lua_Number.sizeof);
+
+mixin template LUAI_MAXALIGN(){
+	lua_Number n;
+	double u;
+	void *s;
+	lua_Integer i;
+	c_long l;
+}
+
+
+// lauxlib.h
+enum LUA_ERRFILE = LUA_ERRERR+1;
+enum LUA_LOADED_TABLE = "_LOADED";
+enum LUA_PRELOAD_TABLE = "_PRELOAD";
+
+struct luaL_Reg{
+	const(char)* name;
+	lua_CFunction func;
+}
+
+enum LUAL_NUMSIZES = lua_Integer.sizeof * 16 + lua_Number.sizeof;
+
+enum LUA_NOREF = -2;
+enum LUA_REFNIL = -1;
+
+struct luaL_Buffer{
+	char* b;
+	size_t size;
+	size_t n;
+	lua_State* L;
+	union init{
+		mixin LUAI_MAXALIGN!();
+		char[LUAL_BUFFERSIZE] initb;
+	}
+}
+
+alias LUA_FILEHANDLE = FILE*;
+
+struct luaL_Stream{
+	FILE* f;
+	lua_CFunction closef;
+}
+
+// lua.h
+enum LUA_VERSION_MAJOR = "5";
+enum LUA_VERSION_MINOR = "4";
+enum LUA_VERSION_RELEASE = "2";
+
+enum LUA_VERSION_NUM = 504;
+enum LUA_VERSION_RELEASE_NUM = LUA_VERSION_NUM * 100 + 0;
+
+enum LUA_VERSION = "Lua " ~ LUA_VERSION_MAJOR ~ "." ~ LUA_VERSION_MINOR;
+enum LUA_RELEASE = LUA_VERSION ~ "." ~ LUA_VERSION_RELEASE;
+
+enum LUA_SIGNATURE = "\x1bLua";
+enum LUA_MULTRET = -1;
+
+enum LUA_REGISTRYINDEX = -LUAI_MAXSTACK - 1000;
+
+enum LUA_OK = 0;
+enum LUA_YIELD = 1;
+enum LUA_ERRRUN = 2;
+enum LUA_ERRSYNTAX = 3;
+enum LUA_ERRMEM = 4;
+enum LUA_ERRERR = 5;
+
+enum LUA_TNONE = -1;
+enum LUA_TNIL = 0;
+enum LUA_TBOOLEAN = 1;
+enum LUA_TLIGHTUSERDATA = 2;
+enum LUA_TNUMBER = 3;
+enum LUA_TSTRING = 4;
+enum LUA_TTABLE = 5;
+enum LUA_TFUNCTION = 6;
+enum LUA_TUSERDATA = 7;
+enum LUA_TTHREAD = 8;
+enum LUA_NUMTYPES = 9;
+
+alias LUA_NUMTAGS = LUA_NUMTYPES;
+
+enum LUA_MINSTACK = 20;
+
+enum LUA_RIDX_MAINTHREAD = 1;
+enum LUA_RIDX_GLOBALS = 2;
+enum LUA_RIDX_LAST = LUA_RIDX_GLOBALS;
+
+alias lua_Number = LUA_NUMBER;
+alias lua_Integer = LUA_INTEGER;
+alias lua_Unsigned = LUA_UNSIGNED;
+alias lua_KContext = LUA_KCONTEXT;
+
+struct lua_State;
+
+extern(C) nothrow{
+	alias lua_CFunction = int function(lua_State* L);
+	alias lua_KFunction = int function(lua_State* L, int status, lua_KContext ctx);
+	alias lua_Reader = const(char)* function(lua_State* L, void* ud, size_t* sz);
+	alias lua_Writer = int function(lua_State* L, const(void)* p, size_t sz, void* ud);
+	alias lua_Alloc = void* function(void* ud, void* ptr, size_t osize, size_t nsize);
+	alias lua_WarnFunction = void function(void* ud, const(char)* msg, int tocont);
+}
+
+enum LUA_OPADD = 0;
+enum LUA_OPSUB = 1;
+enum LUA_OPMUL = 2;
+enum LUA_OPMOD = 3;
+enum LUA_OPPOW = 4;
+enum LUA_OPDIV = 5;
+enum LUA_OPIDIV = 6;
+enum LUA_OPBAND = 7;
+enum LUA_OPBOR = 8;
+enum LUA_OPBXOR = 9;
+enum LUA_OPSHL = 10;
+enum LUA_OPSHR = 11;
+enum LUA_OPUNM = 12;
+enum LUA_OPBNOT = 13;
+
+enum LUA_OPEQ = 0;
+enum LUA_OPLT = 1;
+enum LUA_OPLE = 2;
+
+enum LUA_GCSTOP = 0;
+enum LUA_GCRESTART = 1;
+enum LUA_GCCOLLECT = 2;
+enum LUA_GCCOUNT = 3;
+enum LUA_GCCOUNTB = 4;
+enum LUA_GCSTEP = 5;
+enum LUA_GCSETPAUSE = 6;
+enum LUA_GCSETSTEPMUL = 7;
+enum LUA_GCISRUNNING = 9;
+
+enum LUA_HOOKCALL = 0;
+enum LUA_HOOKRET = 1;
+enum LUA_HOOKLINE = 2;
+enum LUA_HOOKCOUNT = 3;
+enum LUA_HOOKTAILRET = 4;
+
+enum LUA_MASKCALL = 1 << LUA_HOOKCALL;
+enum LUA_MASKRET = 1 << LUA_HOOKRET;
+enum LUA_MASKLINE = 1 << LUA_HOOKLINE;
+enum LUA_MASKCOUNT = 1 << LUA_HOOKCOUNT;
+
+struct lua_Debug{
+	int event;
+	const(char)* name;
+	const(char)* namewhat;
+	const(char)* what;
+	const(char)* source;
+	size_t srclen;
+	int currentline;
+	int linedefined;
+	int lastlinedefined;
+	ubyte nups;
+	ubyte nparams;
+	char isvararg;
+	char istailcall;
+	ushort ftransfer;
+	ushort ntransfer;
+	char[LUA_IDSIZE] short_src;
+	private void* i_ci;
+}
+
+alias lua_Hook = extern(C) void function(lua_State*, lua_Debug*) nothrow;
+
+// lualib.h
+enum LUA_VERSUFFIX = "_" ~ LUA_VERSION_MAJOR ~ "_" ~ LUA_VERSION_MINOR;
+enum LUA_COLIBNAME = "coroutine";
+enum LUA_TABLIBNAME = "table";
+enum LUA_IOLIBNAME = "io";
+enum LUA_OSLIBNAME = "os";
+enum LUA_STRLIBNAME = "string";
+enum LUA_UTF8LIBNAME = "utf8";
+enum LUA_MATHLIBNAME = "math";
+enum LUA_DBLIBNAME = "debug";
+enum LUA_LOADLIBNAME = "package";