Add make_instance() helper function.
[luabind.git] / luabind / detail / make_instance.hpp
blob8021959645ee6a787e0d401a168551b75d3bce2c
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 {
14 template <class T>
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));
24 lua_pop(L, 1);
26 return std::make_pair(
27 class_ids.get_local(typeid(*p))
28 , dynamic_cast<void*>(const_cast<T*>(p))
32 template <class T>
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);
39 template <class T>
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>());
45 template <class T>
46 class_rep* get_pointee_class(class_map const& classes, T*)
48 return classes.get(registered_class<T>::id);
51 template <class P>
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));
60 lua_pop(L, 1);
62 class_rep* cls = classes.get(dynamic_id);
64 if (!cls)
65 cls = get_pointee_class(classes, get_pointer(p));
67 return cls;
70 // Create an appropriate instance holder for the given pointer like object.
71 template <class P>
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);
78 if (!cls)
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));
89 try
91 new (storage) holder_type(p, dynamic.first, dynamic.second, cls);
93 catch (...)
95 instance->deallocate(storage);
96 lua_pop(L, 1);
97 throw;
100 instance->set_instance(static_cast<holder_type*>(storage));
103 }} // namespace luabind::detail
105 #endif // LUABIND_DETAIL_MAKE_INSTANCE_090310_HPP