Index: /trunk/nv/lua/lua_dispatch.hh
===================================================================
--- /trunk/nv/lua/lua_dispatch.hh	(revision 212)
+++ /trunk/nv/lua/lua_dispatch.hh	(revision 212)
@@ -0,0 +1,178 @@
+// 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
+//
+// TODO: the calls are supported only up to 4 parameters because:
+//    -- if you have more than 4 params, you're doing something wrong
+//    -- once the Variadic Templates cometh, for great justice we will win!
+//
+// TODO: this is a job for std::forward, but I'll take care of it later
+
+#ifndef NV_LUA_DISPATCH_HH
+#define NV_LUA_DISPATCH_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
+	{
+		typedef int (__cdecl *lfunction) (struct lua_State *L);
+
+		namespace detail
+		{
+			template < typename R >
+			struct dispatcher
+			{
+				static int call( lua_State* L, int, R (*func)() )
+				{
+					push_value( L, func() ); return 1;
+				}
+				template < typename T1 >
+				static int call( lua_State* L, int index, R (*func)( T1 ) )
+				{
+					push_value( L, func( get_value<T1>( L, index + 0 ) ) ); return 1;
+				}
+				template < typename T1, typename T2 >
+				static int call( lua_State* L, int index, R (*func)( T1, T2 ) )
+				{
+					push_value( L, func( get_value<T1>( L, index + 0 ),	get_value<T2>( L, index + 1 ) ) ); return 1;
+				}
+				template < typename T1, typename T2, typename T3 >
+				static int call( lua_State* L, int index, R (*func)( T1, T2, T3 ) )
+				{
+					push_value( L, func( get_value<T1>( L, index + 0 ), get_value<T2>( L, index + 1 ), get_value<T3>( L, index + 2 ) ) ); return 1;
+				}
+				template < typename T1, typename T2, typename T3, typename T4 >
+				static int call( lua_State* L, int index, R (*func)( T1, T2, T3, T4 ) )
+				{
+					push_value( L, func( get_value<T1>( L, index + 0 ), get_value<T2>( L, index + 1 ), get_value<T3>( L, index + 2 ), get_value<T4>( L, index + 3 ) ) ); return 1;
+				}
+				template < class C >
+				static int call( lua_State* L, int, C& c, R (C::*func)() )
+				{
+					push_value( L, (c.*func)() ); return 1;
+				}
+				template < class C, typename T1 >
+				static int call( lua_State* L, int index, C& c, R (C::*func)( T1 ) )
+				{
+					push_value( L, (c.*func)( get_value<T1>( L, index + 0 ) ) ); return 1;
+				}
+				template < class C, typename T1, typename T2 >
+				static int call( lua_State* L, int index, C& c, R (C::*func)( T1, T2 ) )
+				{
+					push_value( L, (c.*func)( get_value<T1>( L, index + 0 ),	get_value<T2>( L, index + 1 ) ) ); return 1;
+				}
+				template < class C, typename T1, typename T2, typename T3 >
+				static int call( lua_State* L, int index, C& c, R (C::*func)( T1, T2, T3 ) )
+				{
+					push_value( L, (c.*func)( get_value<T1>( L, index + 0 ), get_value<T2>( L, index + 1 ), get_value<T3>( L, index + 2 ) ) ); return 1;
+				}
+				template < class C, typename T1, typename T2, typename T3, typename T4 >
+				static int call( lua_State* L, int index, C& c, R (C::*func)( T1, T2, T3, T4 ) )
+				{
+					push_value( L, (c.*func)( get_value<T1>( L, index + 0 ), get_value<T2>( L, index + 1 ), get_value<T3>( L, index + 2 ), get_value<T4>( L, index + 3 ) ) ); return 1;
+				}
+			};
+			
+			template <>
+			struct dispatcher< void >
+			{
+				static int call( lua_State*, int, void (*func)() )
+				{
+					func(); return 0;
+				}
+				template < typename T1 >
+				static int call( lua_State* L, int index, void (*func)( T1 ) )
+				{
+					func( get_value<T1>( L, index + 0 ) ); return 0;
+				}
+				template < typename T1, typename T2 >
+				static int call( lua_State* L, int index, void (*func)( T1, T2 ) )
+				{
+					func( get_value<T1>( L, index + 0 ), get_value<T2>( L, index + 1 ) ); return 0;
+				}
+				template < typename T1, typename T2, typename T3 >
+				static int call( lua_State* L, int index, void (*func)( T1, T2, T3 ) )
+				{
+					func( get_value<T1>( L, index + 0 ), get_value<T2>( L, index + 1 ), get_value<T3>( L, index + 2 ) ); return 0;
+				}
+				template < typename T1, typename T2, typename T3, typename T4 >
+				static int call( lua_State* L, int index, void (*func)( T1, T2, T3, T4 ) )
+				{
+					func( get_value<T1>( L, index + 0 ), get_value<T2>( L, index + 1 ), get_value<T3>( L, index + 2 ), get_value<T4>( L, index + 3 ) ); return 0;
+				}
+				template < class C >
+				static int call( lua_State*, int, C& c, void (C::*func)() )
+				{
+					(c.*func)(); return 0;
+				}
+				template < class C, typename T1 >
+				static int call( lua_State* L, int index, C& c, void (C::*func)( T1 ) )
+				{
+					(c.*func)( get_value<T1>( L, index + 0 ) ); return 0;
+				}
+				template < class C, typename T1, typename T2 >
+				static int call( lua_State* L, int index, C& c, void (C::*func)( T1, T2 ) )
+				{
+					(c.*func)( get_value<T1>( L, index + 0 ),	get_value<T2>( L, index + 1 ) ); return 0;
+				}
+				template < class C, typename T1, typename T2, typename T3 >
+				static int call( lua_State* L, int index, C& c, void (C::*func)( T1, T2, T3 ) )
+				{
+					(c.*func)( get_value<T1>( L, index + 0 ), get_value<T2>( L, index + 1 ), get_value<T3>( L, index + 2 ) ); return 0;
+				}
+				template < class C, typename T1, typename T2, typename T3, typename T4 >
+				static int call( lua_State* L, int index, C& c, void (C::*func)( T1, T2, T3, T4 ) )
+				{
+					(c.*func)( get_value<T1>( L, index + 0 ), get_value<T2>( L, index + 1 ), get_value<T3>( L, index + 2 ), get_value<T4>( L, index + 3 ) ); return 0;
+				}
+
+			};
+
+			template < typename F, F* f > 
+			int function_wrapper( lua_State* L ) 
+			{
+				return dispatcher<typename return_type<F>::type>::call( L, 1, f );
+			}
+
+			template < typename C, typename F, F* f > 
+			int object_method_wrapper( lua_State* L ) 
+			{
+				C* c = to_object( L, 1 );
+				return dispatcher<typename return_type<F>::type>::call( L, c, 2, f );
+			}
+
+			template < typename C, typename F, F* f > 
+			int fixed_method_wrapper( lua_State* L ) 
+			{
+				C* c = (C*)to_pointer( L, nv::lua::upvalue_index(1) );
+				return dispatcher<typename return_type<F>::type>::call( L, c, 1, f );
+			}
+			
+			template< typename F >
+			int call( lua_State* L, int index, F func )
+			{
+				return dispatcher<typename return_type<F>::type>::call( L, index, func );
+			}
+
+			template< class C, typename F >
+			int call( lua_State* L, int index, C& c, F func )
+			{
+				return dispatcher<typename return_type<F>::type>::call( L, index, c, func );
+			}
+
+		}
+
+	}
+
+}
+
+#endif // NV_LUA_DISPATCH_HH
Index: /trunk/nv/lua/lua_state.hh
===================================================================
--- /trunk/nv/lua/lua_state.hh	(revision 211)
+++ /trunk/nv/lua/lua_state.hh	(revision 212)
@@ -12,9 +12,9 @@
 #include <nv/common.hh>
 #include <nv/flags.hh>
+
 #include <nv/lua/lua_path.hh>
 #include <nv/lua/lua_values.hh>
+#include <nv/lua/lua_dispatch.hh>
 #include <string>
-
-struct lua_State;
 
 namespace nv
@@ -26,5 +26,6 @@
 		const int ret_multi = -1;
 
-		class state;
+		int upvalue_index( int i );
+
 		typedef int reference;
 
@@ -131,4 +132,10 @@
 
 			bool is_defined( const path& p ) { return is_defined( p, m_global ); }
+			void register_native_function( lfunction f, const char* name );
+			template < typename F, F* f >
+			void register_function( const char* name )
+			{
+				register_native_function( detail::function_wrapper< F, f >, name );
+			}
 		protected:
 			bool is_defined( const path& p, bool global );
@@ -178,4 +185,10 @@
 			void store_metadata( object* o, const std::string& metaname, void* pointer );
 			void unregister_object( object * o );
+			void register_native_object_method( const char* lua_name, const char* name, lfunction f );
+			template < typename F, F* f >
+			void register_object_method( const char* lua_name, const char* name )
+			{
+				register_native_object_method( lua_name, name, detail::object_method_wrapper< typename memfn_class_type<F>, F, f > );
+			}
 			void register_enum( type_database* db, const std::string& name, const std::string& prefix = std::string() );
 			operator lua_State*() { return m_state; }
Index: /trunk/src/lua/lua_state.cc
===================================================================
--- /trunk/src/lua/lua_state.cc	(revision 211)
+++ /trunk/src/lua/lua_state.cc	(revision 212)
@@ -251,4 +251,13 @@
 }
 
+
+void lua::state_wrapper::register_native_function( lfunction f, const char* name )
+{
+	if ( m_global ) push_global_table();
+	lua_pushcfunction( m_state, f );
+	lua_setfield( m_state, -2, name );
+	if ( m_global ) pop_global_table();
+}
+
 void lua::state::log_stack()
 {
@@ -287,4 +296,16 @@
 	if ( t == nullptr ) return ref_none;
 	return register_object( o, t->name.c_str() );
+}
+
+void lua::state::register_native_object_method( const char* lua_name, const char* name, lfunction f )
+{
+	stack_guard guard( this );
+	lua_getglobal( m_state, lua_name );
+	if ( lua_isnil( m_state, -1 ) )
+	{
+		NV_THROW( runtime_error, std::string( lua_name ) + " type not registered!" );
+	}
+	lua_pushcfunction( m_state, f );
+	lua_setfield( m_state, -2, name );
 }
 
@@ -411,2 +432,7 @@
 	lua_settop( m_state, m_level );
 }
+
+int nv::lua::upvalue_index( int i )
+{
+	return lua_upvalueindex(i);
+}
