Re: Solved. Re: Fwd: Inspecting objects

Thomas Nelson <[email protected]>
Newsgroups gmane.comp.lang.lua.bind.user
Message-ID <[email protected]>
Here's the patch Nigel,

I've added a method called "has_method" to the wrap_base class.  This 
method calls the deceptively named "do_call_member_selection" which 
actually doesn't call a member selection, it instead leaves it on the 
top of the stack. We check the result pop it and then return whether or 
not it was a function.

It would be easy enough to expand that to check for any sort of member 
and will save you a trip to the interpreter from your C code.


On 3/19/2010 2:56 PM, Nigel Atkinson wrote:
> On Fri, 2010-03-19 at 11:11 -0700, Thomas Nelson wrote:
>    
>> Solved... My bad.  It turns out it had to do with how I was exporting
>> the object... turns out it's helpful to wait till after you've created
>> the instance before you inject a back ref.
>>      
> Glad you got it sorted!
>
>    
>> Any interest on the list for a patch with the following enhancements:
>> 1) Export a luabind::wrap_base derived object to an arbitrary
>> table/namespace in the lua from C++
>> 2) Allow methods to be overridden on a per instance basis
>>      
> I thought you could already do this?
>
>    
>> 3) Examine an object from C++ to determine if a method has been defined
>> on an instance.
>>      
> I'd interested to see how you have done it...  at the moment I use a Lua
> function to do that job, which I call from C++.
>
>    
>> todos
>> 1) When exporting via item 1, allow the programmer to specify a lua class.
>> Right now you can only specify a C++ class that has been exported via
>> luabind.  I want to be able to export as a class that has been derived
>> on the lua side.
>>
>> 2) There are some problems with the function over rides that seem to be
>> based pretty deeply in how lua handles method calls with a self.
>> so defining:
>>
>> function MainMenu:OnMenu(args)
>>
>>       print("boo");
>>
>> end
>>
>> works, however
>>
>> function foo(self, args)
>>
>>       print ("ack");
>>
>> end
>> MainMenu.OnMenu = foo;
>>
>> breaks.
>>      
> That's weird... it should work!
>
> What about
>
> function MainMenu.OnMenu( self, args )
>
> 	print( "ack" )
>
> end
>
> I'd be very surprised if that does not work.
>
>
> Nigel
>
>

------------------------------------------------------------------------------
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
luabind.diffs (text/plain, 8.3 KB)
Left file: H:\development\reference copies\luabind-0.9\luabind\back_reference.hpp
Right file: H:\development\eidolon\external\luabind\luabind\back_reference.hpp
78c78,88
<   
---
> 
> 
>   inline void inject_backref(lua_State*, void*, void*)
>   {}
> 
>   template <class T>
>   void inject_backref(lua_State* L, T* p, wrap_base*)
>   {
> 	  weak_ref(get_main_thread(L), 1).swap(wrap_access::ref(*p));
>   }
> 
87,88c97,101
<         detail::wrap_access::ref(*w).get(L);
<         return true;
---
> 		if (detail::wrap_access::ref(*w).is_valid())
> 		{
> 			detail::wrap_access::ref(*w).get(L);
> 			return true;
> 		}
Left file: H:\development\reference copies\luabind-0.9\luabind\weak_ref.hpp
Right file: H:\development\eidolon\external\luabind\luabind\weak_ref.hpp
50a51
> 		bool is_valid() const { return (m_impl != 0); }
Left file: H:\development\reference copies\luabind-0.9\luabind\wrapper_base.hpp
Right file: H:\development\eidolon\external\luabind\luabind\wrapper_base.hpp
29a30
> #include <luabind/function.hpp>
31a33,34
> #include <luabind/back_reference.hpp>
> #include <luabind/detail/make_instance.hpp>
35a39
> 
39a44,45
> 	struct wrap_base;
> 
50a57,65
> 
> 		template <class T>
> 		bool export_to_stack(lua_State *L, T *that)
> 		{
> 			detail::make_instance<T *>(L, that);
> 			weak_ref(L, -1).swap(wrap_access::ref(*that));
> 
> 			return true;
> 		}
62a78,102
> 		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);
> 			if (lua_isnil(L, -1))
> 				return false;
> 
> 			detail::do_call_member_selection(L, name);
> 
> 			result = (detail::is_luabind_function(L, -1) || lua_isfunction(L, -1));
> 			lua_pop(L, 1);
> 
> 			return result;
> 		}
> 
> 
68a109,137
> 
> 	template < class C >
> 	bool export_to_table_as(lua_State *L, C *self, const char *valuename, const char *tablename = NULL)
> 	{
> 		if (tablename)
> 		{
> 			lua_pushstring(L, tablename);
> 			lua_gettable(L, LUA_GLOBALSINDEX);
> 
> 			if (!lua_istable(L, -1))
> 			{
> 				lua_pop(L, 1);
> 
> 				lua_newtable(L);
> 				lua_pushstring(L, tablename);
> 				lua_pushvalue(L, -2);
> 				lua_settable(L, LUA_GLOBALSINDEX);
> 			}
> 		}
> 		else
> 		{
> 			lua_pushvalue(L, LUA_GLOBALSINDEX);
> 		}
> 		lua_pushstring(L, valuename);
> 		detail::export_to_stack<C>(L, self);
> 		lua_settable(L, -3);
> 		lua_pop(L, 1);
> 		return true;
> 	}
96a166,186
> 	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) );
> 	}
> 
99,108c189,198
< 				, 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
110,112c200,202
< 			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;
114,115c204,205
< 			// 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
117,125c207,210
< 			// TODO: what happens if this virtual function is
< 			// dispatched from a lua thread where the state
< 			// pointer is different?
< 
< 			// 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);
---
> 		// get the function
> 		m_self.get(L);
> 		assert(!lua_isnil(L, -1));
> 		detail::do_call_member_selection(L, name);
127,131c212,216
< 			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");
> 		}
133,134c218,219
< 			// push the self reference as the first parameter
< 			m_self.get(L);
---
> 		// push the self reference as the first parameter
> 		m_self.get(L);
136,140c221,225
< 			// 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);
> 	}
151a237,267
> 
> 	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
> 			);
> 	}
> 
Left file: H:\development\reference copies\luabind-0.9\src\weak_ref.cpp
Right file: H:\development\eidolon\external\luabind\src\weak_ref.cpp
78c78
<             lua_pushvalue(s, index);
---
> 			lua_pushvalue(s, (index < 0) ? index - 1: index);
Left file: H:\development\reference copies\luabind-0.9\src\wrapper_base.cpp
Right file: H:\development\eidolon\external\luabind\src\wrapper_base.cpp
32c32,33
< namespace luabind { namespace detail
---
> namespace luabind { 
> namespace detail
36,37c37,44
< 		object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, -1));
< 		lua_pop(L, 1); // pop self
---
> 		object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, -1));	//get_instance(L, -1);
> 	
> 		lua_pushstring(L, name);
> 		lua_gettable(L, -2);
> 		lua_remove(L, -2);
> 		if (!lua_isnil(L, -1))
> 			return;
> 		lua_pop(L, 1);
55c62,66
< }}
---
> 
> 
> }
> 
> }
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.