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® 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;