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