1 // Copyright Daniel Wallin 2009. Use, modification and distribution is
2 // subject to the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 #ifndef LUABIND_DETAIL_MAKE_INSTANCE_090310_HPP
6 # define LUABIND_DETAIL_MAKE_INSTANCE_090310_HPP
8 # include <boost/type_traits/is_polymorphic.hpp>
9 # include <luabind/detail/inheritance.hpp>
10 # include <luabind/detail/object_rep.hpp>
12 namespace luabind
{ namespace detail
{
15 std::pair
<class_id
, void*> get_dynamic_class_aux(
16 lua_State
* L
, T
const* p
, mpl::true_
)
18 lua_pushstring(L
, "__luabind_class_id_map");
19 lua_rawget(L
, LUA_REGISTRYINDEX
);
21 class_id_map
& class_ids
= *static_cast<class_id_map
*>(
22 lua_touserdata(L
, -1));
26 return std::make_pair(
27 class_ids
.get_local(typeid(*p
))
28 , dynamic_cast<void*>(const_cast<T
*>(p
))
33 std::pair
<class_id
, void*> get_dynamic_class_aux(
34 lua_State
*, T
const* p
, mpl::false_
)
36 return std::make_pair(registered_class
<T
>::id
, (void*)p
);
40 std::pair
<class_id
, void*> get_dynamic_class(lua_State
* L
, T
* p
)
42 return get_dynamic_class_aux(L
, p
, boost::is_polymorphic
<T
>());
46 class_rep
* get_pointee_class(class_map
const& classes
, T
*)
48 return classes
.get(registered_class
<T
>::id
);
52 class_rep
* get_pointee_class(lua_State
* L
, P
const& p
, class_id dynamic_id
)
54 lua_pushstring(L
, "__luabind_class_map");
55 lua_rawget(L
, LUA_REGISTRYINDEX
);
57 class_map
const& classes
= *static_cast<class_map
*>(
58 lua_touserdata(L
, -1));
62 class_rep
* cls
= classes
.get(dynamic_id
);
65 cls
= get_pointee_class(classes
, get_pointer(p
));
70 // Create an appropriate instance holder for the given pointer like object.
72 void make_instance(lua_State
* L
, P p
)
74 std::pair
<class_id
, void*> dynamic
= get_dynamic_class(L
, get_pointer(p
));
76 class_rep
* cls
= get_pointee_class(L
, p
, dynamic
.first
);
80 throw std::runtime_error("Trying to use unregistered class");
83 object_rep
* instance
= push_new_instance(L
, cls
);
85 typedef pointer_holder
<P
> holder_type
;
87 void* storage
= instance
->allocate(sizeof(holder_type
));
91 new (storage
) holder_type(p
, dynamic
.first
, dynamic
.second
, cls
);
95 instance
->deallocate(storage
);
100 instance
->set_instance(static_cast<holder_type
*>(storage
));
103 }} // namespace luabind::detail
105 #endif // LUABIND_DETAIL_MAKE_INSTANCE_090310_HPP