13
0

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

@ -1,7 +1,8 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2016, Robin Gareus <robin@gareus.org>
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
@ -39,6 +40,17 @@
#include <string>
#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_MINOR_VERSION 0
#define LUABRIDGE_VERSION 200
@ -137,6 +149,6 @@ inline void setHideMetatables (bool shouldHide)
Security::setHideMetatables (shouldHide);
}
}
} // end Namespace
#endif

View File

@ -1,7 +1,8 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2016, Robin Gareus <robin@gareus.org>
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
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.
@ -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.
@ -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.
@ -408,6 +567,11 @@ struct CFunc
return 0;
}
static int gcNOOPMethod (lua_State* L)
{
return 0;
}
//--------------------------------------------------------------------------
/**
lua_CFunction to get a class data member.
@ -424,6 +588,20 @@ struct CFunc
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.
@ -439,4 +617,393 @@ struct CFunc
c->**mp = Stack <T>::get (L, 2);
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 isBoolean () const { return type () == LUA_TBOOLEAN; }
inline bool isNumber () const { return type () == LUA_TNUMBER; }
inline bool isString () const { return type () == LUA_TSTRING; }
inline bool isTable () const { return type () == LUA_TTABLE; }

View File

@ -2,6 +2,7 @@
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2016, Robin Gareus <robin@gareus.org>
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
@ -482,6 +483,8 @@ private:
}
else
{
lua_pop (L, 1);
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
rawgetfield (L, -1, "__class");
rawgetfield (L, -1, "__const");
@ -674,6 +677,7 @@ private:
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a property member.
@ -797,6 +801,21 @@ private:
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.
@ -812,6 +831,16 @@ private:
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.
@ -829,6 +858,28 @@ private:
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.
@ -859,8 +910,216 @@ private:
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:
//----------------------------------------------------------------------------
/**
@ -1032,6 +1291,25 @@ public:
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.
@ -1086,6 +1364,19 @@ public:
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.
@ -1108,6 +1399,143 @@ public:
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.
@ -1120,6 +1548,16 @@ public:
{
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);
}
/* vim: set et sw=2: */

View File

@ -2,6 +2,7 @@
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2016, Robin Gareus <robin@gareus.org>
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
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`.

View File

@ -89,6 +89,16 @@ struct TypeTraits
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.
*/
/** @{ */

View File

@ -1,7 +1,8 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2016, Robin Gareus <robin@gareus.org>
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
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.
*/
inline void* const getPointer ()
inline void* getPointer () const
{
return m_p;
}
@ -610,7 +611,7 @@ struct UserdataSharedHelper <C, true>
either be of the intrusive variety, or in the style of the RefCountedPtr
type provided by LuaBridge (that uses a global hash table).
*/
template <class C, bool byContainer>
template <class C, bool byContainer, bool isEnum>
struct StackHelper
{
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.
*/
template <class T>
struct StackHelper <T, false>
struct StackHelper <T, false, false>
{
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)
{
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)
{
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);
}
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);
}
@ -704,7 +723,7 @@ struct Stack <T* const>
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);
}
@ -719,7 +738,7 @@ struct Stack <T const*>
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);
}
@ -734,7 +753,7 @@ struct Stack <T const* const>
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);
}
@ -761,8 +780,8 @@ struct Stack <T&>
template <class C, bool byContainer>
struct RefStackHelper
{
typedef C return_type;
typedef C return_type;
static inline void push (lua_State* L, C const& t)
{
UserdataSharedHelper <C,
@ -781,12 +800,12 @@ struct RefStackHelper
template <class T>
struct RefStackHelper <T, false>
{
typedef T const& return_type;
static inline void push (lua_State* L, T const& t)
{
UserdataPtr::push (L, &t);
}
typedef T const& return_type;
static inline void push (lua_State* L, T const& t)
{
UserdataPtr::push (L, &t);
}
static return_type get (lua_State* L, int index)
{

View File

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