Index: trunk/nv/lua/lua_function.hh
===================================================================
--- trunk/nv/lua/lua_function.hh	(revision 182)
+++ trunk/nv/lua/lua_function.hh	(revision 182)
@@ -0,0 +1,101 @@
+// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+#ifndef NV_LUA_FUNCTION_HH
+#define NV_LUA_FUNCTION_HH
+
+#include <nv/common.hh>
+#include <nv/string.hh>
+#include <nv/lua/lua_values.hh>
+#include <nv/lua/lua_path.hh>
+
+struct lua_State;
+
+namespace nv
+{
+	namespace lua
+	{
+
+		class state;
+
+		class function_base
+		{
+		public:
+			function_base( lua_State* L, const path& a_path, bool global = true );
+			function_base( const function_base& func );
+			function_base& operator=( const function_base& func );
+			~function_base();
+		protected:
+			void retrieve();
+			void call( int args, int results );
+
+		protected:
+			int m_ref;
+			lua_State* L;
+		};
+
+		template < typename R >
+		class function : public function_base
+		{
+		public:
+			function( lua_State *L, const path& a_path, bool global = true )
+				: function_base( L, a_path, global )
+			{
+			}
+
+			R operator()()
+			{
+				retrieve();
+				return call_result<R>(0);
+			}
+
+			template <typename T1>
+			R operator()( const T1& p1 )
+			{
+				retrieve();
+				detail::push_value( L, p1 );
+				return call_result<R>(1);
+			}
+
+			template <typename T1, typename T2>
+			R operator()(const T1& p1, const T2& p2)
+			{
+				retrieve();
+				detail::push_values( L, p1, p2 );
+				return call_result<R>(2);
+			}
+
+			template <typename T1, typename T2, typename T3>
+			R operator()(const T1& p1, const T2& p2, const T3& p3)
+			{
+				retrieve();
+				detail::push_values( L, p1, p2, p3 );
+				return call_result<R>(3);
+			}
+		protected:
+			template< typename RR >
+			R call_result( int params )
+			{
+				call( params, 1 );
+				R value;
+				detail::pop_value( L, value );
+				return value;
+			}
+		};
+ 
+		// I actually wonder whether this hack will work everywhere
+ 		template<>
+ 		template<>
+ 		inline void function<void>::call_result<void>( int params )
+ 		{
+ 			call( params, 1 );
+ 		}
+
+	} // namespace lua
+
+} // namespace nv
+
+#endif // NV_LUA_HH
Index: trunk/nv/lua/lua_values.hh
===================================================================
--- trunk/nv/lua/lua_values.hh	(revision 182)
+++ trunk/nv/lua/lua_values.hh	(revision 182)
@@ -0,0 +1,77 @@
+// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+#ifndef NV_LUA_VALUES_HH
+#define NV_LUA_VALUES_HH
+
+#include <nv/common.hh>
+#include <nv/string.hh>
+
+struct lua_State;
+
+namespace nv
+{
+	namespace lua
+	{
+		template < typename T >
+		struct pass_traits
+		{
+		};
+
+
+		struct passer
+		{
+			virtual void push( lua_State *L ) const = 0;
+		};
+
+		template < typename T >
+		struct returner
+		{
+			virtual void pop( lua_State *L ) = 0;
+			operator T() { return value; }
+			operator const T() const { return value; }
+		protected:
+			T value;
+		};
+
+		namespace detail
+		{
+			void push_value( lua_State *L, long n );
+			void push_value( lua_State *L, double n );
+			void push_value( lua_State *L, bool n );
+			void push_value( lua_State *L, const std::string& s );
+			void push_value( lua_State *L, const char* s );
+			void push_value( lua_State *L, object* o );
+			void push_value( lua_State *L, void* p );
+			void push_value( lua_State *L, const passer& p );
+
+			template < typename T1 >
+			void push_values( lua_State *L, const T1& p1 ) { push_value( L, p1 ); }
+			template < typename T1, typename T2 >
+			void push_values( lua_State *L, const T1& p1, const T2& p2 ) { push_value( L, p1 ); push_value( L, p2 ); }
+			template < typename T1, typename T2, typename T3 >
+			void push_values( lua_State *L, const T1& p1, const T2& p2, const T3& p3 ) { push_value( L, p1 ); push_value( L, p2 ); push_value( L, p3 ); }
+			template < typename T1, typename T2, typename T3, typename T4 >
+			void push_values( lua_State *L, const T1& p1, const T2& p2, const T3& p3, const T4& p4 ) { push_value( L, p1 ); push_value( L, p2 ); push_value( L, p3 ); push_value( L, p4 ); }
+			template < typename T1, typename T2, typename T3, typename T4, typename T5 >
+			void push_values( lua_State *L, const T1& p1, const T2& p2, const T3& p3, const T4& p4, const T5& p5 ) { push_value( L, p1 ); push_value( L, p2 ); push_value( L, p3 ); push_value( L, p4 ); push_value( L, p5 ); }
+
+			void pop_value( lua_State *L, long& n );
+			void pop_value( lua_State *L, double& n );
+			void pop_value( lua_State *L, bool& n );
+			void pop_value( lua_State *L, std::string& s );
+			void pop_value( lua_State *L, object*& o );
+			void pop_value( lua_State *L, void*& p );
+			template < typename T >
+			void pop_value( lua_State *L, T& p ) { p.pop(L); }
+
+		}
+
+	} // namespace lua
+
+} // namespace nv
+
+#endif // NV_LUA_VALUES_HH
Index: trunk/src/lua/lua_function.cc
===================================================================
--- trunk/src/lua/lua_function.cc	(revision 182)
+++ trunk/src/lua/lua_function.cc	(revision 182)
@@ -0,0 +1,66 @@
+// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+#include <nv/lua/lua_function.hh>
+
+#include <nv/lua/lua_raw.hh>
+
+using namespace nv;
+
+lua::function_base::function_base( lua_State* L, const path& a_path, bool global /*= true*/ ) : L(L)
+{
+	if ( !a_path.resolve( L, global ) )
+	{
+		lua_pop( L, 1 );
+		throw std::runtime_error("not a valid path - " + a_path.to_string() );
+	}
+
+	if ( !lua_isfunction( L, -1 ) ) 
+	{
+		lua_pop( L, 1 );
+		throw std::runtime_error("not a valid function - " + a_path.to_string() );
+	}
+	m_ref = luaL_ref( L, LUA_REGISTRYINDEX );
+}
+
+lua::function_base::function_base( const function_base& func ) : L(L)
+{
+	lua_rawgeti( L, LUA_REGISTRYINDEX, func.m_ref );
+	m_ref = luaL_ref( L, LUA_REGISTRYINDEX );
+}
+
+lua::function_base::~function_base()
+{
+	luaL_unref( L, LUA_REGISTRYINDEX, m_ref );
+}
+
+lua::function_base& lua::function_base::operator=(const function_base& func)
+{
+	if ( this != &func ) 
+	{
+		L = func.L;
+		lua_rawgeti( L, LUA_REGISTRYINDEX, func.m_ref );
+		m_ref = luaL_ref( L, LUA_REGISTRYINDEX );
+	}
+	return *this;
+}
+
+void lua::function_base::retrieve()
+{
+	lua_rawgeti( L, LUA_REGISTRYINDEX, m_ref );
+}
+
+void lua::function_base::call( int args, int results )
+{
+	int status = lua_pcall( L, args, results, 0 );
+	if ( status != 0 )
+	{
+		std::string error = lua_tostring( L, -1 );
+		lua_pop( L, 1 );
+		throw std::runtime_error(error.c_str());
+	}
+}
+
Index: trunk/src/lua/lua_values.cc
===================================================================
--- trunk/src/lua/lua_values.cc	(revision 182)
+++ trunk/src/lua/lua_values.cc	(revision 182)
@@ -0,0 +1,104 @@
+// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+#include "nv/lua/lua_values.hh"
+
+#include "nv/lua/lua_raw.hh"
+#include "nv/object.hh"
+
+void nv::lua::detail::push_value( lua_State *L, long n )
+{
+	lua_pushinteger( L, n );
+}
+
+void nv::lua::detail::push_value( lua_State *L, double d )
+{
+	lua_pushnumber( L, d );
+}
+
+void nv::lua::detail::push_value( lua_State *L, bool n )
+{
+	lua_pushboolean( L, n );
+}
+
+void nv::lua::detail::push_value( lua_State *L, const char* s )
+{
+	lua_pushstring( L, s );
+}
+
+void nv::lua::detail::push_value( lua_State *L, const std::string& s )
+{
+	lua_pushstring( L, s.c_str() );
+}
+
+void nv::lua::detail::push_value( lua_State *L, object* o )
+{
+	if ( o == nullptr )
+	{
+		lua_pushnil( L );
+	}
+	else
+	{
+		lua_rawgeti( L, LUA_REGISTRYINDEX, o->get_lua_index() );
+	}
+}
+
+void nv::lua::detail::push_value( lua_State *L, void* p )
+{
+	lua_pushlightuserdata( L, p );
+}
+
+void nv::lua::detail::push_value( lua_State *L, const passer& p )
+{
+	p.push(L);
+}
+
+void nv::lua::detail::pop_value( lua_State *L, long& n )
+{
+	n = lua_tointeger( L, -1 );
+	lua_pop( L, 1 );
+}
+
+void nv::lua::detail::pop_value( lua_State *L, double& d )
+{
+	d = lua_tonumber( L, -1 );
+	lua_pop( L, 1 );
+}
+
+void nv::lua::detail::pop_value( lua_State *L, bool& n )
+{
+	n = lua_toboolean( L, -1 ) != 0;
+	lua_pop( L, 1 );
+}
+
+void nv::lua::detail::pop_value( lua_State *L, std::string& s )
+{
+	s = lua_tostring( L, -1 ); 
+	lua_pop( L, 1 );
+}
+
+void nv::lua::detail::pop_value( lua_State *L, object*& o )
+{
+	o = nullptr;
+	if ( lua_istable( L , -1 ) )
+	{
+		lua_pushstring( L, "__ptr" );
+		lua_rawget( L, -1 );
+		if ( lua_isuserdata( L, -1 ) )
+		{
+			o = (object*)( lua_touserdata( L, -1 ) );
+		} 
+		lua_pop( L, 1 );
+	}
+	lua_pop( L, 1 );
+}
+
+void nv::lua::detail::pop_value( lua_State *L, void*& p )
+{
+	p = lua_touserdata( L, -1 );
+	lua_pop( L, 1 );
+}
+
