Re: Solved: Introspection and navel gazing

"Thomas Nelson" <[email protected]>
Newsgroups gmane.comp.lang.lua.bind.user
Message-ID <637FA65E8891457E9023CB324CD3F291@Spawn>
It took some digging but I was barking up the wrong tree... for some reason
I kept thinking that I needed to examine the class_info structure as opposed
to the wrapper_base.

The attached diff dose 3 things:
1) Adds weak_ref::is_valid() - inspects a weak_ref and returns true if it
has been initialized. 

2) Adds 2 wrapper_base::has_method functions.  One takes the name of the
method to check for, the other takes a lua state and the name of the method.
They both return true if the method has been defined on the lua side.  The
version without the lua state will use the state registered in the wrapper's
weak_ref if any.

bool wrapper_base::has_method(const char *name);
bool wrapper_base::has_method(lua_State *L, const char *name);

3) Added an extra signature to wrapper_base::call.  The new signature takes
a lua_State * and will execute the method on the supplied stack rather than
the one registered in the weak_ref.
wrapper_base::call( const char *name, ... )
wrapper_base::call( lua_State *L, const char *name, ... )


> -----Original Message-----
> From: Thomas Nelson [mailto:[email protected]]
> 
> Perhaps I'm going about this in entirely the wrong way, or this may not
> even
> be possible as things are now... or I'm misunderstanding something. So
> some
> pointers here would be appreciated.
> 
> A long winded description:
> In the (perhaps oversimplified) code below is a class NavelGazer. An
> instance of this class may be created in the C++ and passed to Lua or it
> may
> be created by a Lua script.
> 
> It may also be subclassed in lua and have new methods added.
> 
> I need to be able to examine an instance of NavelGazer from C++ and see if
> an arbitrarily named method has been defined in the lua subclass.

------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev

_______________________________________________
luabind-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/luabind-user
luabindudiff.txt (text/plain, 8.4 KB)
Index: E:/development/eidolon/external/luabind/src/wrapper_base.cpp
===================================================================
--- E:/development/eidolon/external/luabind/src/wrapper_base.cpp	(revision 449)
+++ E:/development/eidolon/external/luabind/src/wrapper_base.cpp	(revision 452)
@@ -29,7 +29,8 @@
 #include <luabind/detail/class_rep.hpp>
 #include <luabind/detail/stack_utils.hpp>
 
-namespace luabind { namespace detail
+namespace luabind { 
+namespace detail
 {
 	LUABIND_API void do_call_member_selection(lua_State* L, char const* name)
 	{
@@ -52,4 +53,37 @@
 		lua_gettable(L, -2);
 		lua_remove(L, -2); // remove the crep table
 	}
-}}
+
+	LUABIND_API bool do_check_member_selection(lua_State* L, char const* name)
+	{
+		bool result(true);
+
+		object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, -1));
+		lua_pop(L, 1); // pop self
+
+		obj->crep()->get_table(L); // push the crep table
+		lua_pushstring(L, name);
+		lua_gettable(L, -2);
+		lua_remove(L, -2); // remove the crep table
+
+		if (!is_luabind_function(L, -1))
+		{	// this is not a luabind exported function
+			lua_pop(L, 1);
+
+			obj->crep()->get_default_table(L); // push the crep table
+			lua_pushstring(L, name);
+			lua_gettable(L, -2);
+			lua_remove(L, -2); // remove the crep table
+			result = (lua_isfunction(L, -1) != 0);
+		}
+
+		lua_pop(L, 1);
+
+		return result;
+	}
+
+
+
+}
+
+}
Index: E:/development/eidolon/external/luabind/luabind/wrapper_base.hpp
===================================================================
--- E:/development/eidolon/external/luabind/luabind/wrapper_base.hpp	(revision 449)
+++ E:/development/eidolon/external/luabind/luabind/wrapper_base.hpp	(revision 452)
@@ -48,6 +48,11 @@
 		// on the top of the stack (the input self reference will
 		// be popped)
 		LUABIND_API void do_call_member_selection(lua_State* L, char const* name);
+
+		// checks to see if named method is a member.  The input is 
+		// the self reference on the stack.  (the input is popped 
+		// by this call
+		LUABIND_API bool do_check_member_selection(lua_State* L, char const* name);
 	}
 
 	struct wrapped_self_t: weak_ref
@@ -60,6 +65,23 @@
 		friend struct detail::wrap_access;
 		wrap_base() {}
 
+		bool is_valid() const { return m_self.is_valid(); }
+
+		bool has_method(const char *name) const
+		{
+			lua_State* L = m_self.state();
+			return has_method(L, name);
+		}
+
+		bool has_method(lua_State *L, const char *name) const
+		{
+			bool result(false);
+
+			m_self.get(L);
+			assert(!lua_isnil(L, -1));
+			return detail::do_check_member_selection(L, name);
+		}
+
     #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/wrapper_base.hpp>, 1))
 	#include BOOST_PP_ITERATE()
 
@@ -94,51 +116,67 @@
 #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
 #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n
 
+	template < class R 
+		BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)
+	>
+	typename boost::mpl::if_<
+		boost::is_void<R>,
+		luabind::detail::proxy_member_void_caller<
+			boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> 
+		>,
+		luabind::detail::proxy_member_caller<
+			R, 
+			boost::tuples::tuple<
+				BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)
+		> 
+	> 
+	>::type
+	call(char const* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _), detail::type_<R>* = 0) const
+	{
+		lua_State* L = m_self.state();
+		return call<R>(L, name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a) );
+	}
+
 	template<class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
 		typename boost::mpl::if_<boost::is_void<R>
-				, luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
-				, luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type
-				call(char const* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _), detail::type_<R>* = 0) const
-		{
-			typedef boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> tuple_t;
-	#if BOOST_PP_ITERATION() == 0
-			tuple_t args;
-	#else
-			tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a));
-	#endif
+			, luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
+			, luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type
+	call(lua_State* L, char const* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _), detail::type_<R>* = 0) const
+	{
+		typedef boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> tuple_t;
+#	if BOOST_PP_ITERATION() == 0
+		tuple_t args;
+#	else
+		tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a));
+#	endif
 
-			typedef typename boost::mpl::if_<boost::is_void<R>
-				, luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
-				, luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type proxy_type;
+		typedef typename boost::mpl::if_<boost::is_void<R>
+			, luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
+			, luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type proxy_type;
 
-			// this will be cleaned up by the proxy object
-			// once the call has been made
+		// this will be cleaned up by the proxy object
+		// once the call has been made
 
-			// TODO: what happens if this virtual function is
-			// dispatched from a lua thread where the state
-			// pointer is different?
+		// get the function
+		m_self.get(L);
+		assert(!lua_isnil(L, -1));
+		detail::do_call_member_selection(L, name);
 
-			// get the function
-			lua_State* L = m_self.state();
-			m_self.get(L);
-			assert(!lua_isnil(L, -1));
-			detail::do_call_member_selection(L, name);
+		if (lua_isnil(L, -1))
+		{
+			lua_pop(L, 1);
+			throw std::runtime_error("Attempt to call nonexistent function");
+		}
 
-			if (lua_isnil(L, -1))
-			{
-				lua_pop(L, 1);
-				throw std::runtime_error("Attempt to call nonexistent function");
-			}
+		// push the self reference as the first parameter
+		m_self.get(L);
 
-			// push the self reference as the first parameter
-			m_self.get(L);
+		// now the function and self objects
+		// are on the stack. These will both
+		// be popped by pcall
+		return proxy_type(L, args);
+	}
 
-			// now the function and self objects
-			// are on the stack. These will both
-			// be popped by pcall
-			return proxy_type(L, args);
-		}
-
 #undef LUABIND_CALL_MEMBER_NAME
 #undef LUABIND_OPERATOR_PARAMS
 #undef LUABIND_TUPLE_PARAMS
@@ -150,6 +188,37 @@
 #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
 #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n
 
+	template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class A)	>
+	typename boost::mpl::if_<
+		boost::is_void<R>,
+		detail::proxy_member_void_caller<
+			boost::tuples::tuple<
+				BOOST_PP_ENUM(N, LUABIND_TUPLE_PARAMS, _)
+			>
+		>,
+		detail::proxy_member_caller<
+			R,
+			boost::tuples::tuple<
+				BOOST_PP_ENUM(N, LUABIND_TUPLE_PARAMS, _)
+			>
+		>
+	>::type
+	call_member(
+		lua_State *L,
+		wrap_base const* self,
+		char const* fn
+		BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, A, &a),
+		detail::type_<R>* = 0
+	)
+	{
+		return self->call(L,
+			fn
+			BOOST_PP_ENUM_TRAILING_PARAMS(N, a),
+			(detail::type_<R>*)0
+			);
+	}
+
+
     template<
         class R 
         BOOST_PP_ENUM_TRAILING_PARAMS(N, class A)
Index: E:/development/eidolon/external/luabind/luabind/weak_ref.hpp
===================================================================
--- E:/development/eidolon/external/luabind/luabind/weak_ref.hpp	(revision 449)
+++ E:/development/eidolon/external/luabind/luabind/weak_ref.hpp	(revision 452)
@@ -48,6 +48,7 @@
         lua_State* state() const;
         void get(lua_State* L) const;
 
+		bool is_valid() const { return (m_impl != 0); }
     private:
         struct impl;
         impl* m_impl;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.