customize LuaBridge

* introduce boost::shared_ptr support
* support enum & const
* allow to add non-class member functions
* STL iterators (vector, list, set, bitset & map)
* support reference arguments (framecnt_t&)
* add support for arrays of basic types (e.g. float*, int*)
* fix compiler warnings
This commit is contained in:
Robin Gareus 2016-02-21 19:25:42 +01:00
parent 5b40e073e9
commit 12a58015a3
8 changed files with 1137 additions and 23 deletions

View file

@ -2,6 +2,7 @@
/* /*
https://github.com/vinniefalco/LuaBridge https://github.com/vinniefalco/LuaBridge
Copyright 2016, Robin Gareus <robin@gareus.org>
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed Copyright 2007, Nathan Reed
@ -39,6 +40,17 @@
#include <string> #include <string>
#include <typeinfo> #include <typeinfo>
#include <bitset>
#include <list>
#include <map>
#include <set>
#include <vector>
#include <inttypes.h>
#include <boost/ref.hpp>
#include <boost/type_traits.hpp>
#include <boost/shared_ptr.hpp>
#define LUABRIDGE_MAJOR_VERSION 2 #define LUABRIDGE_MAJOR_VERSION 2
#define LUABRIDGE_MINOR_VERSION 0 #define LUABRIDGE_MINOR_VERSION 0
#define LUABRIDGE_VERSION 200 #define LUABRIDGE_VERSION 200
@ -137,6 +149,6 @@ inline void setHideMetatables (bool shouldHide)
Security::setHideMetatables (shouldHide); Security::setHideMetatables (shouldHide);
} }
} } // end Namespace
#endif #endif

View file

@ -2,6 +2,7 @@
/* /*
https://github.com/vinniefalco/LuaBridge https://github.com/vinniefalco/LuaBridge
Copyright 2016, Robin Gareus <robin@gareus.org>
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php) License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
@ -290,6 +291,95 @@ struct CFunc
} }
}; };
template <class MemFnPtr, class T,
class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
struct CallMemberPtr
{
typedef typename FuncTraits <MemFnPtr>::Params Params;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
boost::shared_ptr<T>* const t = Userdata::get <boost::shared_ptr<T> > (L, 1, false);
T* const tt = t->get();
if (!tt) {
return luaL_error (L, "shared_ptr is nil");
}
MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
ArgList <Params, 2> args (L);
Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (tt, fnptr, args));
return 1;
}
};
template <class T, class R>
struct CastMemberPtr
{
static int f (lua_State* L)
{
boost::shared_ptr<T> t = luabridge::Stack<boost::shared_ptr<T> >::get (L, 1);
Stack <boost::shared_ptr<R> >::push (L, boost::dynamic_pointer_cast<R> (t));
return 1;
}
};
template <class T>
struct PtrNullCheck
{
static int f (lua_State* L)
{
boost::shared_ptr<T> t = luabridge::Stack<boost::shared_ptr<T> >::get (L, 1);
Stack <bool>::push (L, t == 0);
return 1;
}
};
template <class T>
struct WPtrNullCheck
{
static int f (lua_State* L)
{
bool rv = true;
boost::weak_ptr<T> tw = luabridge::Stack<boost::weak_ptr<T> >::get (L, 1);
boost::shared_ptr<T> const t = tw.lock();
if (t) {
T* const tt = t.get();
rv = (tt == 0);
}
Stack <bool>::push (L, rv);
return 1;
}
};
template <class MemFnPtr, class T,
class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
struct CallMemberWPtr
{
typedef typename FuncTraits <MemFnPtr>::Params Params;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
boost::weak_ptr<T>* const tw = Userdata::get <boost::weak_ptr<T> > (L, 1, false);
boost::shared_ptr<T> const t = tw->lock();
if (!t) {
return luaL_error (L, "cannot lock weak_ptr");
}
T* const tt = t.get();
if (!tt) {
return luaL_error (L, "weak_ptr is nil");
}
MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
ArgList <Params, 2> args (L);
Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (tt, fnptr, args));
return 1;
}
};
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** /**
lua_CFunction to call a class member function with no return value. lua_CFunction to call a class member function with no return value.
@ -333,6 +423,51 @@ struct CFunc
} }
}; };
template <class MemFnPtr, class T>
struct CallMemberPtr <MemFnPtr, T, void>
{
typedef typename FuncTraits <MemFnPtr>::Params Params;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
boost::shared_ptr<T>* const t = Userdata::get <boost::shared_ptr<T> > (L, 1, false);
T* const tt = t->get();
MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
ArgList <Params, 2> args (L);
FuncTraits <MemFnPtr>::call (tt, fnptr, args);
return 0;
}
};
template <class MemFnPtr, class T>
struct CallMemberWPtr <MemFnPtr, T, void>
{
typedef typename FuncTraits <MemFnPtr>::Params Params;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
boost::weak_ptr<T>* const tw = Userdata::get <boost::weak_ptr<T> > (L, 1, false);
boost::shared_ptr<T> const t = tw->lock();
if (!t) {
return luaL_error (L, "cannot lock weak_ptr");
}
T* const tt = t.get();
if (!tt) {
return luaL_error (L, "weak_ptr is nil");
}
MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
ArgList <Params, 2> args (L);
FuncTraits <MemFnPtr>::call (tt, fnptr, args);
return 0;
}
};
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
lua_CFunction to call a class member lua_CFunction. lua_CFunction to call a class member lua_CFunction.
@ -396,6 +531,30 @@ struct CFunc
} }
}; };
template <class MemFnPtr>
struct CallMemberPtrFunctionHelper
{
typedef typename FuncTraits <MemFnPtr>::ClassType T;
static void add (lua_State* L, char const* name, MemFnPtr mf)
{
new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
lua_pushcclosure (L, &CallMemberPtr <MemFnPtr, T>::f, 1);
rawsetfield (L, -3, name); // class table
}
};
template <class MemFnPtr>
struct CallMemberWPtrFunctionHelper
{
typedef typename FuncTraits <MemFnPtr>::ClassType T;
static void add (lua_State* L, char const* name, MemFnPtr mf)
{
new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
lua_pushcclosure (L, &CallMemberWPtr <MemFnPtr, T>::f, 1);
rawsetfield (L, -3, name); // class table
}
};
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
__gc metamethod for a class. __gc metamethod for a class.
@ -408,6 +567,11 @@ struct CFunc
return 0; return 0;
} }
static int gcNOOPMethod (lua_State* L)
{
return 0;
}
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
lua_CFunction to get a class data member. lua_CFunction to get a class data member.
@ -424,6 +588,20 @@ struct CFunc
return 1; return 1;
} }
//--------------------------------------------------------------------------
/**
lua_CFunction to get a constant (enum)
*/
template <typename U>
static int getConst (lua_State* L)
{
U *v = static_cast <U *> (lua_touserdata (L, lua_upvalueindex (1)));
assert (v);
Stack <U>::push (L, *v);
return 1;
}
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
lua_CFunction to set a class data member. lua_CFunction to set a class data member.
@ -439,4 +617,393 @@ struct CFunc
c->**mp = Stack <T>::get (L, 2); c->**mp = Stack <T>::get (L, 2);
return 0; return 0;
} }
//--------------------------------------------------------------------------
// metatable callback for "array[index]"
template <typename T>
static int array_index (lua_State* L) {
T** parray = (T**) luaL_checkudata (L, 1, typeid(T).name());
int const index = luabridge::Stack<int>::get (L, 2);
luabridge::Stack<T>::push (L, (*parray)[index-1]);
return 1;
}
// metatable callback for "array[index] = value"
template <typename T>
static int array_newindex (lua_State* L) {
T** parray = (T**) luaL_checkudata (L, 1, typeid(T).name());
int const index = luabridge::Stack<int>::get (L, 2);
T const value = luabridge::Stack<T>::get (L, 3);
(*parray)[index-1] = value;
return 0;
}
template <typename T>
static int getArray (lua_State* L) {
T *v = luabridge::Stack<T*>::get (L, 1);
T** parray = (T**) lua_newuserdata(L, sizeof(T**));
*parray = v;
luaL_getmetatable(L, typeid(T).name());
lua_setmetatable(L, -2);
return 1;
}
// copy complete c array to lua table
template <typename T>
static int getTable (lua_State* L) {
T *v = luabridge::Stack<T*>::get (L, 1);
const int cnt = luabridge::Stack<int>::get (L, 2);
LuaRef t (L);
t = newTable (L);
for (int i = 0; i < cnt; ++i) {
t[i + 1] = v[i];
}
t.push(L);
return 1;
}
// copy lua table to c array
template <typename T>
static int setTable (lua_State* L) {
T *v = luabridge::Stack<T*>::get (L, 1);
LuaRef t (LuaRef::fromStack(L, 2));
const int cnt = luabridge::Stack<int>::get (L, 3);
for (int i = 0; i < cnt; ++i) {
v[i] = t[i + 1];
}
return 0;
}
//--------------------------------------------------------------------------
/**
C++ STL iterators
*/
// read lua table into C++ std::list
template <class T, class C>
static int tableToListHelper (lua_State *L, C * const t)
{
if (!t) { return luaL_error (L, "invalid pointer to std::list<>/std::vector"); }
if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
lua_pushvalue (L, -1);
lua_pushnil (L);
while (lua_next (L, -2)) {
lua_pushvalue (L, -2);
T const value = Stack<T>::get (L, -2);
t->push_back (value);
lua_pop (L, 2);
}
lua_pop (L, 1);
lua_pop (L, 2);
Stack<C>::push (L, *t);
return 1;
}
template <class T, class C>
static int tableToList (lua_State *L)
{
C * const t = Userdata::get<C> (L, 1, false);
return tableToListHelper<T, C> (L, t);
}
template <class T, class C>
static int ptrTableToList (lua_State *L)
{
boost::shared_ptr<C> const* const t = Userdata::get<boost::shared_ptr<C> > (L, 1, true);
if (!t) { return luaL_error (L, "cannot derefencee shared_ptr"); }
return tableToListHelper<T, C> (L, t->get());
}
//--------------------------------------------------------------------------
template <class T, class C>
static int listIterIter (lua_State *L) {
typedef typename C::const_iterator IterType;
IterType * const end = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (2)));
IterType * const iter = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (1)));
assert (end);
assert (iter);
if ((*iter) == (*end)) {
return 0;
}
Stack <T>::push (L, **iter);
++(*iter);
return 1;
}
// generate an iterator
template <class T, class C>
static int listIterHelper (lua_State *L, C * const t)
{
if (!t) { return luaL_error (L, "invalid pointer to std::list<>/std::vector"); }
typedef typename C::const_iterator IterType;
new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->begin());
new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->end());
lua_pushcclosure (L, listIterIter<T, C>, 2);
return 1;
}
template <class T, class C>
static int listIter (lua_State *L)
{
C * const t = Userdata::get <C> (L, 1, false);
return listIterHelper<T, C> (L, t);
}
template <class T, class C>
static int ptrListIter (lua_State *L)
{
boost::shared_ptr<C> const* const t = Userdata::get <boost::shared_ptr<C> >(L, 1, true);
if (!t) { return luaL_error (L, "cannot derefencee shared_ptr"); }
return listIterHelper<T, C> (L, t->get());
}
//--------------------------------------------------------------------------
// generate table from std::list
template <class T, class C>
static int listToTableHelper (lua_State *L, C const* const t)
{
if (!t) { return luaL_error (L, "invalid pointer to std::list<>/std::vector"); }
#if 0 // direct lua api
lua_createtable(L, t->size(), 0);
int newTable = lua_gettop(L);
int index = 1;
for (typename C::const_iterator iter = t->begin(); iter != t->end(); ++iter, ++index) {
Stack<T>::push(L, (*iter));
lua_rawseti (L, newTable, index);
}
#else // luabridge way
LuaRef v (L);
v = newTable (L);
int index = 1;
for (typename C::const_iterator iter = t->begin(); iter != t->end(); ++iter, ++index) {
v[index] = (*iter);
}
v.push(L);
#endif
return 1;
}
template <class T, class C>
static int listToTable (lua_State *L)
{
C const* const t = Userdata::get <C> (L, 1, true);
return listToTableHelper<T, C> (L, t);
}
template <class T, class C>
static int ptrListToTable (lua_State *L)
{
boost::shared_ptr<C> const* const t = Userdata::get <boost::shared_ptr<C> > (L, 1, true);
if (!t) { return luaL_error (L, "cannot derefencee shared_ptr"); }
return listToTableHelper<T, C> (L, t->get());
}
//--------------------------------------------------------------------------
// generate std::map from table
template <class K, class V>
static int tableToMap (lua_State *L)
{
typedef std::map<K, V> C;
C * const t = Userdata::get <C> (L, 1, true);
if (!t) { return luaL_error (L, "invalid pointer to std::map"); }
if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
lua_pushvalue (L, -1);
lua_pushnil (L);
while (lua_next (L, -2)) {
lua_pushvalue (L, -2);
K const key = Stack<K>::get (L, -1);
V const value = Stack<V>::get (L, -2);
t->insert (std::pair<K,V> (key, value));
//(*t)[key] = value;
lua_pop (L, 2);
}
lua_pop (L, 1);
lua_pop (L, 2);
Stack<C>::push (L, *t);
return 1;
}
// iterate over a std::map
template <class K, class V>
static int mapIterIter (lua_State *L)
{
typedef std::map<K, V> C;
typedef typename C::const_iterator IterType;
IterType * const end = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (2)));
IterType * const iter = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (1)));
assert (end);
assert (iter);
if ((*iter) == (*end)) {
return 0;
}
Stack <K>::push (L, (*iter)->first);
Stack <V>::push (L, (*iter)->second);
++(*iter);
return 2;
}
// generate iterator
template <class K, class V>
static int mapIter (lua_State *L)
{
typedef std::map<K, V> C;
C * const t = Userdata::get <C> (L, 1, false);
if (!t) { return luaL_error (L, "invalid pointer to std::map"); }
typedef typename C::const_iterator IterType;
new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->begin());
new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->end());
lua_pushcclosure (L, mapIterIter<K, V>, 2);
return 1;
}
// generate table from std::map
template <class K, class V>
static int mapToTable (lua_State *L)
{
typedef std::map<K, V> C;
C const* const t = Userdata::get <C> (L, 1, true);
if (!t) { return luaL_error (L, "invalid pointer to std::map"); }
LuaRef v (L);
v = newTable (L);
for (typename C::const_iterator iter = t->begin(); iter != t->end(); ++iter) {
v[(*iter).first] = (*iter).second;
}
v.push(L);
return 1;
}
//--------------------------------------------------------------------------
// generate std::set from table keys ( table[member] = true )
// http://www.lua.org/pil/11.5.html
template <class T>
static int tableToSet (lua_State *L)
{
typedef std::set<T> C;
C * const t = Userdata::get <C> (L, 1, true);
if (!t) { return luaL_error (L, "invalid pointer to std::set"); }
if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
lua_pushvalue (L, -1);
lua_pushnil (L);
while (lua_next (L, -2)) {
lua_pushvalue (L, -2);
T const member = Stack<T>::get (L, -1);
bool const v = Stack<bool>::get (L, -2);
if (v) {
t->insert (member);
}
lua_pop (L, 2);
}
lua_pop (L, 1);
lua_pop (L, 2);
Stack<C>::push (L, *t);
return 1;
}
// iterate over a std::set, explicit "true" value.
// compare to http://www.lua.org/pil/11.5.html
template <class T>
static int setIterIter (lua_State *L)
{
typedef std::set<T> C;
typedef typename C::const_iterator IterType;
IterType * const end = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (2)));
IterType * const iter = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (1)));
assert (end);
assert (iter);
if ((*iter) == (*end)) {
return 0;
}
Stack <T>::push (L, **iter);
Stack <bool>::push (L, true);
++(*iter);
return 2;
}
// generate iterator
template <class T>
static int setIter (lua_State *L)
{
typedef std::set<T> C;
C * const t = Userdata::get <C> (L, 1, false);
if (!t) { return luaL_error (L, "invalid pointer to std::set"); }
typedef typename C::const_iterator IterType;
new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->begin());
new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->end());
lua_pushcclosure (L, setIterIter<T>, 2);
return 1;
}
// generate table from std::set
template <class T>
static int setToTable (lua_State *L)
{
typedef std::set<T> C;
C const* const t = Userdata::get <C> (L, 1, true);
if (!t) { return luaL_error (L, "invalid pointer to std::set"); }
LuaRef v (L);
v = newTable (L);
for (typename C::const_iterator iter = t->begin(); iter != t->end(); ++iter) {
v[(*iter)] = true;
}
v.push(L);
return 1;
}
//--------------------------------------------------------------------------
// bitset { num = true }
// compare to http://www.lua.org/pil/11.5.html
template <unsigned int T>
static int tableToBitSet (lua_State *L)
{
typedef std::bitset<T> C;
C * const t = Userdata::get <C> (L, 1, true);
if (!t) { return luaL_error (L, "invalid pointer to std::bitset"); }
if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
lua_pushvalue (L, -1);
lua_pushnil (L);
while (lua_next (L, -2)) {
lua_pushvalue (L, -2);
unsigned int const member = Stack<unsigned int>::get (L, -1);
bool const v = Stack<bool>::get (L, -2);
if (member < T && v) {
t->set (member);
}
lua_pop (L, 2);
}
lua_pop (L, 1);
lua_pop (L, 2);
Stack<C>::push (L, *t);
return 1;
}
// generate table from std::bitset
template <unsigned int T>
static int bitSetToTable (lua_State *L)
{
typedef std::bitset<T> C;
C const* const t = Userdata::get <C> (L, 1, true);
if (!t) { return luaL_error (L, "invalid pointer to std::bitset"); }
LuaRef v (L);
v = newTable (L);
for (unsigned int i = 0; i < T; ++i) {
if (t->test (i)) {
v[i] = true;
}
}
v.push(L);
return 1;
}
}; };
/* vim: set et sw=2: */

View file

@ -237,6 +237,7 @@ private:
} }
inline bool isNil () const { return type () == LUA_TNIL; } inline bool isNil () const { return type () == LUA_TNIL; }
inline bool isBoolean () const { return type () == LUA_TBOOLEAN; }
inline bool isNumber () const { return type () == LUA_TNUMBER; } inline bool isNumber () const { return type () == LUA_TNUMBER; }
inline bool isString () const { return type () == LUA_TSTRING; } inline bool isString () const { return type () == LUA_TSTRING; }
inline bool isTable () const { return type () == LUA_TTABLE; } inline bool isTable () const { return type () == LUA_TTABLE; }

View file

@ -2,6 +2,7 @@
/* /*
https://github.com/vinniefalco/LuaBridge https://github.com/vinniefalco/LuaBridge
Copyright 2016, Robin Gareus <robin@gareus.org>
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed Copyright 2007, Nathan Reed
@ -482,6 +483,8 @@ private:
} }
else else
{ {
lua_pop (L, 1);
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
rawgetfield (L, -1, "__class"); rawgetfield (L, -1, "__class");
rawgetfield (L, -1, "__const"); rawgetfield (L, -1, "__const");
@ -674,6 +677,7 @@ private:
return *this; return *this;
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
Add or replace a property member. Add or replace a property member.
@ -797,6 +801,21 @@ private:
return *this; return *this;
} }
template <class MemFn>
Class <T>& addPtrFunction (char const* name, MemFn mf)
{
CFunc::CallMemberPtrFunctionHelper <MemFn>::add (L, name, mf);
return *this;
}
template <class MemFn>
Class <T>& addWPtrFunction (char const* name, MemFn mf)
{
CFunc::CallMemberWPtrFunctionHelper <MemFn>::add (L, name, mf);
return *this;
}
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
Add or replace a member lua_CFunction. Add or replace a member lua_CFunction.
@ -812,6 +831,16 @@ private:
return *this; return *this;
} }
// custom callback - extend existing classes
// with non-class member functions (e.g STL iterator)
Class <T>& addExtCFunction (char const* name, int (*const fp)(lua_State*))
{
assert (lua_istable (L, -1));
lua_pushcclosure (L, fp, 0);
rawsetfield (L, -3, name); // class table
return *this;
}
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
Add or replace a const member lua_CFunction. Add or replace a const member lua_CFunction.
@ -829,6 +858,28 @@ private:
return *this; return *this;
} }
/**
Add or replace a static const data
*/
template <typename U>
Class <T>& addConst (char const* name, const U val)
{
assert (lua_istable (L, -1));
rawgetfield (L, -1, "__propget"); // static
new (lua_newuserdata (L, sizeof (val))) U (val);
lua_pushcclosure (L, &CFunc::getConst <U>, 1);
rawsetfield (L, -2, name);
lua_pop (L, 1);
rawgetfield (L, -1, "__propset"); // static
lua_pushstring (L, name);
lua_pushcclosure (L, &CFunc::readOnlyError, 1);
rawsetfield (L, -2, name);
lua_pop (L, 1);
return *this;
}
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
Add or replace a primary Constructor. Add or replace a primary Constructor.
@ -859,8 +910,216 @@ private:
return *this; return *this;
} }
Class <T>& addVoidConstructor ()
{
return addConstructor <void (*) ()> ();
}
}; };
/** C Array to/from table */
template <typename T>
class Array : public ClassBase
{
public:
Array (char const* name, Namespace const* parent) : ClassBase (parent->L)
{
m_stackSize = parent->m_stackSize + 3;
parent->m_stackSize = 0;
#if 0 // don't allow to duplicates handlers for same array-type
assert (lua_istable (L, -1));
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
if (lua_istable (L, -1)) {
lua_pushnil (L);
lua_pushnil (L);
return;
}
lua_pop (L, 1);
#endif
assert (lua_istable (L, -1));
rawgetfield (L, -1, name);
if (lua_isnil (L, -1))
{
lua_pop (L, 1);
// register array access in global namespace
luaL_newmetatable (L, typeid(T).name());
lua_pushcclosure (L, CFunc::array_index<T>, 0);
lua_setfield(L, -2, "__index");
lua_pushcclosure (L, CFunc::array_newindex<T>, 0);
lua_setfield(L, -2, "__newindex");
lua_pop (L, 1);
createConstTable (name);
lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
rawsetfield (L, -2, "__gc");
createClassTable (name);
lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
rawsetfield (L, -2, "__gc");
createStaticTable (name);
// Map T back to its tables.
lua_pushvalue (L, -1);
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
lua_pushvalue (L, -2);
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
lua_pushvalue (L, -3);
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
assert (lua_istable (L, -1));
lua_pushcclosure (L, &CFunc::getArray <T>, 0);
rawsetfield (L, -3, "array"); // class table
lua_pushcclosure (L, &CFunc::getTable <T>, 0);
rawsetfield (L, -3, "get_table"); // class table
lua_pushcclosure (L, &CFunc::setTable <T>, 0);
rawsetfield (L, -3, "set_table"); // class table
}
else
{
lua_pushnil (L);
lua_pushnil (L);
}
}
Namespace endArray ()
{
return Namespace (this);
}
};
/** Boost Weak & Shared Pointer Class Wrapper */
template <class T>
class WSPtrClass : public ClassBase
{
public:
WSPtrClass (char const* name, Namespace const* parent)
: ClassBase (parent->L)
, weak (name, parent)
, shared (name, parent)
{
m_stackSize = weak.m_stackSize;
parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
lua_pop (L, 3);
}
WSPtrClass (char const* name, Namespace const* parent, void const* const sharedkey, void const* const weakkey)
: ClassBase (parent->L)
, weak (name, parent, weakkey)
, shared (name, parent, sharedkey)
{
m_stackSize = weak.m_stackSize;
parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
lua_pop (L, 3);
}
template <class MemFn>
WSPtrClass <T>& addFunction (char const* name, MemFn mf)
{
set_weak_class ();
CFunc::CallMemberWPtrFunctionHelper <MemFn>::add (L, name, mf);
set_shared_class ();
CFunc::CallMemberPtrFunctionHelper <MemFn>::add (L, name, mf);
return *this;
}
template <class MemFn>
WSPtrClass <T>& addConstructor ()
{
set_weak_class ();
lua_pushcclosure (L,
&weak.ctorPlacementProxy <typename FuncTraits <MemFn>::Params, boost::weak_ptr<T> >, 0);
rawsetfield(L, -2, "__call");
set_shared_class ();
lua_pushcclosure (L,
&shared.ctorPlacementProxy <typename FuncTraits <MemFn>::Params, boost::shared_ptr<T> >, 0);
rawsetfield(L, -2, "__call");
return *this;
}
WSPtrClass <T>& addVoidConstructor ()
{
return addConstructor <void (*) ()> ();
}
WSPtrClass <T>& addExtCFunction (char const* name, int (*const fp)(lua_State*))
{
set_weak_class ();
assert (lua_istable (L, -1));
lua_pushcclosure (L, fp, 0);
rawsetfield (L, -3, name); // class table
set_shared_class ();
assert (lua_istable (L, -1));
lua_pushcclosure (L, fp, 0);
rawsetfield (L, -3, name); // class table
return *this;
}
template <class U>
WSPtrClass <T>& addCast (char const* name)
{
// TODO weak ptr
set_shared_class ();
assert (lua_istable (L, -1));
lua_pushcclosure (L, &CFunc::CastMemberPtr <T, U>::f, 0);
rawsetfield (L, -3, name); // class table
return *this;
}
WSPtrClass <T>& addNullCheck ()
{
set_weak_class ();
assert (lua_istable (L, -1));
lua_pushcclosure (L, &CFunc::WPtrNullCheck <T>::f, 0);
rawsetfield (L, -3, "isnil"); // class table
set_shared_class ();
assert (lua_istable (L, -1));
lua_pushcclosure (L, &CFunc::PtrNullCheck <T>::f, 0);
rawsetfield (L, -3, "isnil"); // class table
return *this;
}
Namespace endClass ()
{
return Namespace (this);
}
private:
void set_weak_class () {
lua_pop (L, 3);
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::weak_ptr<T> >::getStaticKey ());
rawgetfield (L, -1, "__class");
rawgetfield (L, -1, "__const");
lua_insert (L, -3);
lua_insert (L, -2);
}
void set_shared_class () {
lua_pop (L, 3);
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::shared_ptr<T> >::getStaticKey ());
rawgetfield (L, -1, "__class");
rawgetfield (L, -1, "__const");
lua_insert (L, -3);
lua_insert (L, -2);
}
Class<boost::weak_ptr<T> > weak;
Class<boost::shared_ptr<T> > shared;
};
private: private:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** /**
@ -1032,6 +1291,25 @@ public:
return *this; return *this;
} }
template <typename U>
Namespace& addConst (char const* name, const U val)
{
assert (lua_istable (L, -1));
rawgetfield (L, -1, "__propget");
new (lua_newuserdata (L, sizeof (val))) U (val);
lua_pushcclosure (L, &CFunc::getConst <U>, 1);
rawsetfield (L, -2, name);
lua_pop (L, 1);
rawgetfield (L, -1, "__propset");
assert (lua_istable (L, -1));
lua_pushstring (L, name);
lua_pushcclosure (L, &CFunc::readOnlyError, 1);
rawsetfield (L, -2, name);
lua_pop (L, 1);
return *this;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** /**
Add or replace a property. Add or replace a property.
@ -1086,6 +1364,19 @@ public:
return *this; return *this;
} }
//----------------------------------------------------------------------------
/**
Add or replace a array type
*/
template <typename T>
Namespace registerArray (char const* name)
{
return Array <T> (name, this).endArray();
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** /**
Add or replace a lua_CFunction. Add or replace a lua_CFunction.
@ -1108,6 +1399,143 @@ public:
return Class <T> (name, this); return Class <T> (name, this);
} }
/** weak & shared pointer class */
template <class T>
WSPtrClass <T> beginWSPtrClass (char const* name)
{
return WSPtrClass <T> (name, this)
.addNullCheck();
}
//----------------------------------------------------------------------------
template <class K, class V>
Class<std::map<K, V> > beginStdMap (char const* name)
{
typedef std::map<K, V> LT;
typedef std::pair<const K, V> T;
return beginClass<LT> (name)
.addVoidConstructor ()
.addFunction ("empty", &LT::empty)
.addFunction ("size", &LT::size)
.addFunction ("clear", (void (LT::*)())&LT::clear)
.addFunction ("count", (void (LT::*)())&LT::count)
.addExtCFunction ("add", &CFunc::tableToMap<K, V>)
.addExtCFunction ("iter", &CFunc::mapIter<K, V>)
.addExtCFunction ("table", &CFunc::mapToTable<K, V>);
}
template <class T>
Class<std::set<T> > beginStdSet (char const* name)
{
typedef std::set<T> LT;
return beginClass<LT> (name)
.addVoidConstructor ()
.addFunction ("clear", (void (LT::*)())&LT::clear)
.addFunction ("empty", &LT::empty)
.addFunction ("size", &LT::size)
.addExtCFunction ("add", &CFunc::tableToSet<T>)
.addExtCFunction ("iter", &CFunc::setIter<T>)
.addExtCFunction ("table", &CFunc::setToTable<T>);
}
template <unsigned int T>
Class<std::bitset<T> > beginStdBitSet (char const* name)
{
typedef std::bitset<T> BS;
return beginClass<BS> (name)
.addVoidConstructor ()
.addFunction ("reset", (BS& (BS::*)())&BS::reset)
.addFunction ("set", (BS& (BS::*)(size_t, bool))&BS::set)
.addFunction ("count", &BS::count)
.addFunction ("any", &BS::any)
.addFunction ("none", &BS::none)
.addFunction ("test", &BS::test)
.addFunction ("size", &BS::size)
.addExtCFunction ("add", &CFunc::tableToBitSet<T>)
.addExtCFunction ("table", &CFunc::bitSetToTable<T>);
}
template <class T>
Class<std::list<T> > beginConstStdList (char const* name)
{
typedef std::list<T> LT;
return beginClass<LT> (name)
.addVoidConstructor ()
.addFunction ("empty", &LT::empty)
.addFunction ("size", &LT::size)
.addFunction ("reverse", &LT::reverse)
.addExtCFunction ("iter", &CFunc::listIter<T, LT>)
.addExtCFunction ("table", &CFunc::listToTable<T, LT>);
}
template <class T>
Class<std::list<T> > beginStdList (char const* name)
{
typedef std::list<T> LT;
return beginConstStdList<T> (name)
.addFunction ("unique", (void (LT::*)())&LT::unique)
.addFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
.addExtCFunction ("add", &CFunc::tableToList<T, LT>);
}
template <class T>
Class<std::vector<T> > beginStdVector (char const* name)
{
typedef std::vector<T> LT;
typedef typename std::vector<T>::reference T_REF;
typedef typename std::vector<T>::size_type T_SIZE;
return beginClass<LT> (name)
.addVoidConstructor ()
.addFunction ("empty", &LT::empty)
.addFunction ("size", &LT::size)
.addFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
.addFunction ("at", (T_REF (LT::*)(T_SIZE))&LT::at)
.addExtCFunction ("add", &CFunc::tableToList<T, LT>)
.addExtCFunction ("iter", &CFunc::listIter<T, LT>)
.addExtCFunction ("table", &CFunc::listToTable<T, LT>);
}
//----------------------------------------------------------------------------
template <class T>
Class<boost::shared_ptr<std::list<T> > > beginPtrStdList (char const* name)
{
typedef std::list<T> LT;
return beginClass<boost::shared_ptr<LT> > (name)
.addVoidConstructor ()
.addPtrFunction ("empty", &LT::empty)
.addPtrFunction ("size", &LT::size)
.addPtrFunction ("reverse", &LT::reverse)
.addPtrFunction ("unique", (void (LT::*)())&LT::unique)
.addPtrFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
.addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
.addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
.addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
}
template <class T>
Class<boost::shared_ptr<std::vector<T> > > beginPtrStdVector (char const* name)
{
typedef std::vector<T> LT;
typedef typename std::vector<T>::reference T_REF;
typedef typename std::vector<T>::size_type T_SIZE;
return beginClass<boost::shared_ptr<LT> > (name)
.addVoidConstructor ()
.addPtrFunction ("empty", &LT::empty)
.addPtrFunction ("empty", &LT::empty)
.addPtrFunction ("size", &LT::size)
.addPtrFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
.addPtrFunction ("at", (T_REF (LT::*)(T_SIZE))&LT::at)
.addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
.addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
.addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** /**
Derive a new class for registrations. Derive a new class for registrations.
@ -1120,6 +1548,16 @@ public:
{ {
return Class <T> (name, this, ClassInfo <U>::getStaticKey ()); return Class <T> (name, this, ClassInfo <U>::getStaticKey ());
} }
template <class T, class U>
WSPtrClass <T> deriveWSPtrClass (char const* name)
{
return WSPtrClass <T> (name, this,
ClassInfo <boost::shared_ptr<U> >::getStaticKey (),
ClassInfo <boost::weak_ptr<U> >::getStaticKey ())
.addNullCheck();
}
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -1134,3 +1572,5 @@ inline Namespace getGlobalNamespace (lua_State* L)
{ {
return Namespace::getGlobalNamespace (L); return Namespace::getGlobalNamespace (L);
} }
/* vim: set et sw=2: */

View file

@ -2,6 +2,7 @@
/* /*
https://github.com/vinniefalco/LuaBridge https://github.com/vinniefalco/LuaBridge
Copyright 2016, Robin Gareus <robin@gareus.org>
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed Copyright 2007, Nathan Reed
@ -281,6 +282,70 @@ struct Stack <unsigned long const&>
} }
}; };
//------------------------------------------------------------------------------
/**
Stack specialization for `long long`.
*/
template <>
struct Stack <long long>
{
static inline void push (lua_State* L, long long value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static inline long long get (lua_State* L, int index)
{
return static_cast <long long> (luaL_checkinteger (L, index));
}
};
template <>
struct Stack <long long const&>
{
static inline void push (lua_State* L, long long value)
{
lua_pushnumber (L, static_cast <lua_Number> (value));
}
static inline long long get (lua_State* L, int index)
{
return static_cast <long long> (luaL_checknumber (L, index));
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `unsigned long long`.
*/
template <>
struct Stack <unsigned long long>
{
static inline void push (lua_State* L, unsigned long long value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static inline unsigned long long get (lua_State* L, int index)
{
return static_cast <unsigned long long> (luaL_checkinteger (L, index));
}
};
template <>
struct Stack <unsigned long long const&>
{
static inline void push (lua_State* L, unsigned long long value)
{
lua_pushnumber (L, static_cast <lua_Number> (value));
}
static inline unsigned long long get (lua_State* L, int index)
{
return static_cast <unsigned long long> (luaL_checknumber (L, index));
}
};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** /**
Stack specialization for `float`. Stack specialization for `float`.

View file

@ -89,6 +89,16 @@ struct TypeTraits
static const bool value = sizeof (test <ContainerTraits <T> >(0)) == sizeof (yes); static const bool value = sizeof (test <ContainerTraits <T> >(0)) == sizeof (yes);
}; };
/** Determine if T is an enum */
template <typename T>
class isEnum
{
public:
//static const bool value = std::is_enum<T>::value; // C++11
static const bool value = boost::is_enum<T>::value;
};
/** Determine if T is const qualified. /** Determine if T is const qualified.
*/ */
/** @{ */ /** @{ */

View file

@ -2,6 +2,7 @@
/* /*
https://github.com/vinniefalco/LuaBridge https://github.com/vinniefalco/LuaBridge
Copyright 2016, Robin Gareus <robin@gareus.org>
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php) License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
@ -68,7 +69,7 @@ protected:
/** /**
Get an untyped pointer to the contained class. Get an untyped pointer to the contained class.
*/ */
inline void* const getPointer () inline void* getPointer () const
{ {
return m_p; return m_p;
} }
@ -610,7 +611,7 @@ struct UserdataSharedHelper <C, true>
either be of the intrusive variety, or in the style of the RefCountedPtr either be of the intrusive variety, or in the style of the RefCountedPtr
type provided by LuaBridge (that uses a global hash table). type provided by LuaBridge (that uses a global hash table).
*/ */
template <class C, bool byContainer> template <class C, bool byContainer, bool isEnum>
struct StackHelper struct StackHelper
{ {
static inline void push (lua_State* L, C const& c) static inline void push (lua_State* L, C const& c)
@ -636,7 +637,7 @@ struct StackHelper
retrieved may result in undefined behavior if Lua garbage collected it. retrieved may result in undefined behavior if Lua garbage collected it.
*/ */
template <class T> template <class T>
struct StackHelper <T, false> struct StackHelper <T, false, false>
{ {
static inline void push (lua_State* L, T const& t) static inline void push (lua_State* L, T const& t)
{ {
@ -649,6 +650,22 @@ struct StackHelper <T, false>
} }
}; };
template <class T>
struct StackHelper <T, false, true>
{
static inline void push (lua_State* L, T const& t)
{
int v = static_cast <int> (t);
lua_pushinteger (L, static_cast <lua_Integer> (v));
}
static inline T get (lua_State* L, int index)
{
int v = static_cast <int> (luaL_checkinteger (L, index));
return T (v);
}
};
//============================================================================== //==============================================================================
/** /**
@ -661,13 +678,15 @@ public:
static inline void push (lua_State* L, T const& t) static inline void push (lua_State* L, T const& t)
{ {
StackHelper <T, StackHelper <T,
TypeTraits::isContainer <T>::value>::push (L, t); TypeTraits::isContainer <T>::value,
TypeTraits::isEnum<T>::value>::push (L, t);
} }
static inline T get (lua_State* L, int index) static inline T get (lua_State* L, int index)
{ {
return StackHelper <T, return StackHelper <T,
TypeTraits::isContainer <T>::value>::get (L, index); TypeTraits::isContainer <T>::value,
TypeTraits::isEnum<T>::value>::get (L, index);
} }
}; };
@ -689,7 +708,7 @@ struct Stack <T*>
UserdataPtr::push (L, p); UserdataPtr::push (L, p);
} }
static inline T* const get (lua_State* L, int index) static inline T* get (lua_State* L, int index)
{ {
return Userdata::get <T> (L, index, false); return Userdata::get <T> (L, index, false);
} }
@ -704,7 +723,7 @@ struct Stack <T* const>
UserdataPtr::push (L, p); UserdataPtr::push (L, p);
} }
static inline T* const get (lua_State* L, int index) static inline T* get (lua_State* L, int index)
{ {
return Userdata::get <T> (L, index, false); return Userdata::get <T> (L, index, false);
} }
@ -719,7 +738,7 @@ struct Stack <T const*>
UserdataPtr::push (L, p); UserdataPtr::push (L, p);
} }
static inline T const* const get (lua_State* L, int index) static inline T const* get (lua_State* L, int index)
{ {
return Userdata::get <T> (L, index, true); return Userdata::get <T> (L, index, true);
} }
@ -734,7 +753,7 @@ struct Stack <T const* const>
UserdataPtr::push (L, p); UserdataPtr::push (L, p);
} }
static inline T const* const get (lua_State* L, int index) static inline T const* get (lua_State* L, int index)
{ {
return Userdata::get <T> (L, index, true); return Userdata::get <T> (L, index, true);
} }
@ -783,10 +802,10 @@ struct RefStackHelper <T, false>
{ {
typedef T const& return_type; typedef T const& return_type;
static inline void push (lua_State* L, T const& t) static inline void push (lua_State* L, T const& t)
{ {
UserdataPtr::push (L, &t); UserdataPtr::push (L, &t);
} }
static return_type get (lua_State* L, int index) static return_type get (lua_State* L, int index)
{ {

View file

@ -1,7 +1,7 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
std::string dumpLuaState(lua_State *L) { static std::string dumpLuaState(lua_State *L) {
std::stringstream ostr; std::stringstream ostr;
int i; int i;
int top = lua_gettop(L); int top = lua_gettop(L);
@ -20,7 +20,7 @@ std::string dumpLuaState(lua_State *L) {
ostr << " " << i << ": " << lua_tonumber(L, i) << "\n"; ostr << " " << i << ": " << lua_tonumber(L, i) << "\n";
break; break;
default: default:
ostr << " " << i << ": TYPE=" << lua_typename(L, t) << "\n"; ostr << " " << i << ": TYPE=" << lua_typename(L, t) << ": " << lua_topointer(L, i)<< "\n";
break; break;
} }
} }