Ole Krüger %!s(int64=10) %!d(string=hai) anos
pai
achega
8f17ec8aa8
Modificáronse 7 ficheiros con 682 adicións e 339 borrados
  1. 27 339
      LICENSE
  2. 25 0
      src/common.h
  3. 102 0
      src/stack.h
  4. 63 0
      src/storage.h
  5. 162 0
      src/types.h
  6. 167 0
      src/userdata.h
  7. 136 0
      src/wrappers.h

+ 27 - 339
LICENSE

@@ -1,339 +1,27 @@
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                            NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
+Copyright (c) 2015, Ole Krüger <ole@vprsm.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* Neither the name of Luwra nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 25 - 0
src/common.h

@@ -0,0 +1,25 @@
+/* Luwra
+ * Minimal-overhead Lua wrapper for C++
+ *
+ * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
+ */
+
+#ifndef LUWRA_COMMON_H_
+#define LUWRA_COMMON_H_
+
+#include <lua.hpp>
+
+// Check for proper Lua version
+#if defined(LUA_VERSION_NUM)
+	#if LUA_VERSION_NUM < 503 || LUA_VERSION >= 600
+		#warning "Luwra has not been tested against your installed version of Lua"
+	#end
+#else
+	#error "Your Lua library does not define LUA_VERSION_NUM"
+#end
+
+#define LUWRA_NS_BEGIN namespace luwra {
+
+#define LUWRA_NS_END }
+
+#endif

+ 102 - 0
src/stack.h

@@ -0,0 +1,102 @@
+/* Luwra
+ * Minimal-overhead Lua wrapper for C++
+ *
+ * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
+ */
+
+#ifndef LUWRA_STACK_H_
+#define LUWRA_STACK_H_
+
+#include "common.h"
+#include "types.h"
+
+#include <utility>
+#include <functional>
+#include <type_traits>
+
+LUWRA_NS_BEGIN
+
+namespace internal {
+	template <typename>
+	struct Layout;
+
+	template <typename R, typename T>
+	struct Layout<R(T)> {
+		template <typename F, typename... A> static inline
+		R direct(State* state, int n, F hook, A&&... args) {
+			return hook(
+				std::forward<A>(args)...,
+				Value<T>::read(state, n)
+			);
+		}
+	};
+
+	template <typename R, typename T1, typename... TR>
+	struct Layout<R(T1, TR...)> {
+		template <typename F, typename... A> static inline
+		R direct(State* state, int n, F hook, A&&... args) {
+			return Layout<TR...>::template direct<F, R>(
+				state,
+				n + 1,
+				hook,
+				std::forward<A>(args)...,
+				Value<T1>::read(state, n)
+			);
+		}
+	};
+}
+
+/**
+ * Assuming a stack layout as follows (where A = A0, A1 ... An):
+ *
+ *   Position | Parameter
+ * 	----------+-----------
+ *   pos + n  | An xn
+ *   ...      | ...
+ *   pos + 1  | A1 x1
+ *   pos + 0  | A0 x0
+ *   ...      | ...
+ *
+ * Given a function `R f(A0, A1, ... An)` you are able to map over
+ * the values on the stack on the stack like so:
+ *
+ *   R my_result = apply(lua_state, pos, f);
+ *
+ * which is equivalent to
+ *
+ *   R my_result = f(x0, x1, ... xn);
+ *
+ * where x0, x1, ... xn are the values on the stack.
+ */
+template <typename R, typename... A> static inline
+R apply(State* state, int pos, R (*funptr)(A...)) {
+	return internal::Layout<R(A...)>::direct(state, pos, funptr);
+}
+
+/**
+ * Same as `apply(state, 1, funptr)`.
+ */
+template <typename R, typename... A> static inline
+R apply(State* state, R (*funptr)(A...)) {
+	return apply(state, 1, funptr);
+}
+
+/**
+ * Specialization of `apply` which works for `std::function`.
+ */
+template <typename R, typename... A> static inline
+R apply(State* state, int pos, std::function<R(A...)> fun) {
+	return internal::Layout<R(A...)>::direct(state, pos, fun);
+}
+
+/**
+ * Same as `apply(state, 1, fun)`.
+ */
+template <typename R, typename... A> static inline
+R apply(State* state, std::function<R(A...)> fun) {
+	return apply(state, 1, fun);
+}
+
+LUWRA_NS_END
+
+#endif

+ 63 - 0
src/storage.h

@@ -0,0 +1,63 @@
+/* Luwra
+ * Minimal-overhead Lua wrapper for C++
+ *
+ * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
+ */
+
+#ifndef LUWRA_STORAGE_H_
+#define LUWRA_STORAGE_H_
+
+#include "common.h"
+
+LUWRA_NS_BEGIN
+
+/**
+ * A seperate execution stack, which acts as a storage unit.
+ */
+struct Storage {
+	State* storage;
+
+	/**
+	 * Create the storage unit.
+	 */
+	inline
+	Storage(State* parent, int capacity = 0) {
+		storage = lua_newthread(parent);
+		lua_pop(parent, 1);
+
+		reserve(capacity);
+	}
+
+	/**
+	 * Make sure at least `n` slots are available.
+	 */
+	inline
+	void reserve(int n) {
+		while (lua_gettop(storage) < n) {
+			lua_pushnil(storage);
+		}
+	}
+
+	/**
+	 * Fill a slot.
+	 */
+	template <typename T> inline
+	void set(int n, T value) {
+		reserve(n);
+		lua_remove(storage, n);
+		Value<T>::push(storage, value);
+		lua_insert(storage, n);
+	}
+
+	/**
+	 * Implicit conversion to a Lua state.
+	 */
+	inline
+	operator State*() {
+		return storage;
+	}
+};
+
+LUWRA_NS_END
+
+#endif

+ 162 - 0
src/types.h

@@ -0,0 +1,162 @@
+/* Luwra
+ * Minimal-overhead Lua wrapper for C++
+ *
+ * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
+ */
+
+#ifndef LUWRA_TYPES_H_
+#define LUWRA_TYPES_H_
+
+#include "common.h"
+
+#include <utility>
+#include <tuple>
+#include <string>
+
+LUWRA_NS_BEGIN
+
+/* Lua types */
+using Integer = lua_Integer;
+using Number = lua_Number;
+using State = lua_State;
+using CFunction = lua_CFunction;
+
+/**
+ * A value on the stack
+ */
+template <typename T>
+struct Value {
+	static_assert(sizeof(T) == -1, "You must not use an unspecialized version of Value");
+
+	/**
+	 * Retrieve the value at position `n`.
+	 */
+	static
+	T read(State*, int);
+
+	/**
+	 * Push the value onto the stack.
+	 */
+	static
+	int push(State*, T);
+};
+
+/**
+ * Define a template specialization of `Value` for `type` with a `retrf(State*, int)` which
+ * extracts it from the stack and a `pushf(State*, type)` which pushes the value on the stack again.
+ * This assumes that only one value will be pushed onto the stack.
+ */
+#define LUWRA_DEF_VALUE(type, retrf, pushf)                       \
+	template <>                                                      \
+	struct Value<type> {                                             \
+		static inline                                                \
+		type read(State* state, int n) {                             \
+			return retrf(state, n);                                  \
+		}                                                            \
+                                                                     \
+		static inline                                                \
+		int push(State* state, type value) {                         \
+			pushf(state, value);                                     \
+			return 1;                                                \
+		}                                                            \
+	}
+
+#ifndef luaL_checkboolean
+	/**
+	 * Check if the value at index `n` is a boolean and retrieve its value.
+	 */
+	#define luaL_checkboolean(state, n) \
+		(luaL_checktype(state, n, LUA_TBOOLEAN), lua_toboolean(state, n))
+#endif
+
+#ifndef luaL_pushstdstring
+	/**
+	 * Push a `std::string` as string onto the stack.
+	 */
+	#define luaL_pushstdstring(state, stdstring) \
+		(lua_pushstring(state, stdstring.c_str()))
+#endif
+
+/* Lua-dependent types */
+LUWRA_DEF_VALUE(Integer,     luaL_checkinteger, lua_pushinteger);
+LUWRA_DEF_VALUE(Number,      luaL_checknumber,  lua_pushnumber);
+
+/* C/C++ types */
+LUWRA_DEF_VALUE(bool,        luaL_checkboolean, lua_pushboolean);
+LUWRA_DEF_VALUE(const char*, luaL_checkstring,  lua_pushstring);
+LUWRA_DEF_VALUE(std::string, luaL_checkstring,  luaL_pushstdstring);
+
+#undef LUWRA_DEF_VALUE
+
+/**
+ * An arbitrary value on an execution stack.
+ * Note: this value is only available as long as it exists on its originating stack.
+ */
+struct Arbitrary {
+	State* state;
+	int index;
+};
+
+template <>
+struct Value<Arbitrary> {
+	static inline
+	Arbitrary read(State* state, int index) {
+		if (index < 0)
+			index = lua_gettop(state) + (index + 1);
+
+		return Arbitrary {state, index};
+	}
+
+	static inline
+	int push(State* state, const Arbitrary& value) {
+		lua_pushvalue(value.state, value.index);
+
+		if (value.state != state)
+			lua_xmove(value.state, state, 1);
+
+		return 1;
+	}
+};
+
+namespace internal {
+	template <typename>
+	struct StackPusher;
+
+	template <size_t I>
+	struct StackPusher<std::index_sequence<I>> {
+		template <typename T> static inline
+		void push(State* state, const T& package) {
+			Value<typename std::tuple_element<I, T>::type>::push(state, std::get<I>(package));
+		}
+	};
+
+	template <size_t I, size_t... Is>
+	struct StackPusher<std::index_sequence<I, Is...>> {
+		template <typename T> static inline
+		void push(State* state, const T& package) {
+			Value<typename std::tuple_element<I, T>::type>::push(state, std::get<I>(package));
+			StackPusher<std::index_sequence<Is...>>::push(state, package);
+		}
+	};
+}
+
+/**
+ * Allows you to use multiple return values.
+ */
+template <typename... A>
+struct Value<std::tuple<A...>> {
+	static inline
+	std::tuple<A...> read(State*, int) {
+		static_assert(sizeof(std::tuple<A...>) == -1, "std::tuples cannot be read from the stack");
+	}
+
+	static inline
+	int push(State* state, const std::tuple<A...>& value) {
+		internal::StackPusher<std::make_index_sequence<sizeof...(A)>>::push(state, value);
+		return sizeof...(A);
+	}
+};
+
+LUWRA_NS_END
+
+#endif

+ 167 - 0
src/userdata.h

@@ -0,0 +1,167 @@
+/* Luwra
+ * Minimal-overhead Lua wrapper for C++
+ *
+ * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
+ */
+
+#ifndef LUWRA_USERDATA_H_
+#define LUWRA_USERDATA_H_
+
+#include "common.h"
+#include "types.h"
+#include "stack.h"
+
+#include <sstream>
+#include <utility>
+
+LUWRA_NS_BEGIN
+
+namespace internal {
+	template <typename T, typename... A>
+	int userdata_ctor(State* state) {
+		return apply(state, [state](A... args) {
+			return Value<T>::push(state, args...);
+		});
+	}
+
+	template <typename T>
+	int userdata_dtor(State* state) {
+		Value<T*>::read(state, 1)->~T();
+		return 0;
+	}
+
+	template <typename T>
+	int userdata_tostring(State* state) {
+		T* instance = Value<T*>::read(state, 1);
+
+		return Value<std::string>::push(
+			state,
+			std::string(T::MetatableName) + ": " + std::to_string(instance)
+		);
+	}
+}
+
+/**
+ * Instances of userdata shall always be used as pointers, because other Lua types can not be
+ * converted to pointers, hence this allows the compiler to differentiate between them.
+ */
+template <typename T>
+struct Value<T*> {
+	static inline
+	T* read(State* state, int n) {
+		return static_cast<T*>(
+			luaL_checkudata(state, n, T::MetatableName)
+		);
+	}
+
+	template <typename... A> static inline
+	int push(State* state, A&&... args) {
+		void* mem = lua_newuserdata(state, sizeof(T));
+
+		if (!mem) {
+			luaL_error(state, "Failed to allocate user data");
+			return -1;
+		}
+
+		// Call constructor on instance
+		new (mem) T(std::forward<A>(args)...);
+
+		// Set metatable for this type
+		luaL_getmetatable(state, T::MetatableName);
+		lua_setmetatable(state, -2);
+
+		return 1;
+	}
+};
+
+/**
+ * Generate the metatable for the userdata type `T`. This function allows you to register methods
+ * which are shared across all instances of this type. A garbage-collector hook is also inserted;
+ * it destructs the underlying type when the garbage-collector says it is time to say good-bye
+ * needed.
+ */
+template <typename T> static inline
+void register_type_metatable(
+	State* state,
+	std::initializer_list<std::pair<const char*, CFunction>> methods,
+	std::initializer_list<std::pair<const char*, CFunction>> meta_methods = {}
+) {
+	luaL_newmetatable(state, T::MetatableName);
+
+	// Register methods
+	lua_pushstring(state, "__index");
+	lua_newtable(state);
+
+	for (auto& method: methods) {
+		lua_pushstring(state, method.first);
+		lua_pushcfunction(state, method.second);
+		lua_rawset(state, -3);
+	}
+
+	lua_rawset(state, -3);
+
+	// Register garbage-collection hook
+	lua_pushstring(state, "__gc");
+	lua_pushcfunction(state, &internal::userdata_dtor<T>);
+	lua_rawset(state, -3);
+
+	// Register string representation function
+	lua_pushstring(state, "__tostring");
+	lua_pushcfunction(state, &internal::userdata_tostring<T>);
+	lua_rawset(state, -3);
+
+	// Insert meta methods
+	for (auto& metamethod: meta_methods) {
+		lua_pushstring(state, metamethod.first);
+		lua_pushcfunction(state, metamethod.second);
+		lua_rawset(state, -3);
+	}
+
+	// Pop meta table off the stack
+	lua_pop(state, -1);
+}
+
+static inline
+void register_userdata_metatable(
+	State* state, const char* name,
+	std::initializer_list<std::pair<const char*, CFunction>> methods,
+	std::initializer_list<std::pair<const char*, CFunction>> meta_methods = {}
+) {
+	// Create meta table
+	luaL_newmetatable(state, name);
+
+	// Prepare for method registration
+	lua_pushstring(state, "__index");
+	lua_newtable(state);
+
+	// Insert methods
+	for (auto& method: methods) {
+		lua_pushstring(state, method.first);
+		lua_pushcfunction(state, method.second);
+		lua_rawset(state, -3);
+	}
+
+	// Commit '__index' field
+	lua_rawset(state, -3);
+
+	// Insert meta methods
+	for (auto& metamethod: meta_methods) {
+		lua_pushstring(state, metamethod.first);
+		lua_pushcfunction(state, metamethod.second);
+		lua_rawset(state, -3);
+	}
+
+	// Pop meta table off the stack
+	lua_pop(state, -1);
+}
+
+/**
+ * Constructor function for a type `T`. Variadic arguments must be used to specify which parameters
+ * to use during construction.
+ */
+template <typename T, typename... A>
+constexpr CFunction WrapConstructor = &internal::userdata_ctor<T, A...>;
+
+LUWRA_NS_END
+
+#endif

+ 136 - 0
src/wrappers.h

@@ -0,0 +1,136 @@
+/* Luwra
+ * Minimal-overhead Lua wrapper for C++
+ *
+ * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
+ */
+
+#ifndef LUWRA_WRAPPERS_H_
+#define LUWRA_WRAPPERS_H_
+
+#include "common.h"
+#include "types.h"
+#include "stack.h"
+
+LUWRA_NS_BEGIN
+
+namespace internal {
+	// Function helpers
+
+	template <typename T>
+	struct FunctionWrapper {
+		static_assert(
+			sizeof(T) == -1,
+			"The FunctionWrapper template expects a function signature as parameter"
+		);
+	};
+
+	template <>
+	struct FunctionWrapper<void()> {
+		template <void(*funptr)()> static
+		int invoke(State*) {
+			funptr();
+			return 0;
+		}
+	};
+
+	template <typename R>
+	struct FunctionWrapper<R()> {
+		template <R(*funptr)()> static
+		int invoke(State* state) {
+			return Value<R>::push(state, funptr());
+		}
+	};
+
+	template <typename... A>
+	struct FunctionWrapper<void(A...)> {
+		template <void (*funptr)(A...)> static
+		int invoke(State* state) {
+			apply(state, funptr);
+			return 0;
+		}
+	};
+
+	template <typename R, typename... A>
+	struct FunctionWrapper<R(A...)> {
+		template <R (*funptr)(A...)> static
+		int invoke(State* state) {
+			return Value<R>::push(
+				state,
+				apply(state, funptr)
+			);
+		}
+	};
+
+	// Method helpers
+
+	template <typename T, typename S>
+	struct MethodWrapper {
+		static_assert(
+			sizeof(T) == -1,
+			"The MethodWrapper template expects a type name and a function signature as parameter"
+		);
+	};
+
+	template <typename T, typename R, typename... A>
+	struct MethodWrapper<T, R(A...)> {
+		using MethodPointerType = R (T::*)(A...);
+		using FunctionSignature = R (T*, A...);
+
+		template <MethodPointerType MethodPointer> static
+		R delegate(T* parent, A... args) {
+			return (parent->*MethodPointer)(std::forward<A>(args)...);
+		}
+	};
+}
+
+/**
+ * Assuming its parameters can be retrieved from the Lua stack, ordinary functions can be wrapped
+ * using the `WrapFunction` instance in order to produce a C function which can be used by the
+ * Lua VM.
+ *
+ * Assuming your function has the following signature:
+ *
+ *   R my_fun(A0, A1 ... An);
+ *
+ * Generate a Lua-compatible like so:
+ *
+ *   CFunction wrapped_fun = WrapFunction<R(A0, A1 ... An), my_fun>;
+ */
+template <
+	typename S,
+	S* FunctionPointer
+>
+constexpr CFunction WrapFunction =
+	&internal::FunctionWrapper<S>::template invoke<FunctionPointer>;
+
+/**
+ * Works similiar to `WrapFunction`. Given a class or struct declaration as follows:
+ *
+ *   struct T {
+ *     R my_method(A0, A1 ... An);
+ *   };
+ *
+ * You might wrap this method easily:
+ *
+ *   CFunction wrapped_meth = WrapMethod<T, R(A0, A1 ... An), &T::my_method>;
+ *
+ * In Lua, assuming `instance` is a userdata instance of type `T`, x0, x1 ... xn are instances
+ * of A0, A1 ... An, and the method has been bound as `my_method`; it is possible to invoke the
+ * method like so:
+ *
+ *   instance:my_method(x0, x1 ... xn)
+ */
+template <
+	typename T,
+	typename S,
+	typename internal::MethodWrapper<T, S>::MethodPointerType MethodPointer
+>
+constexpr CFunction WrapMethod =
+	WrapFunction<
+		internal::MethodWrapper<T, S>::FunctionSignature,
+		internal::MethodWrapper<T, S>::template delegate<MethodPointer>
+	>;
+
+LUWRA_NS_END
+
+#endif