1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
23 #define LUABIND_BUILDING
25 #include <luabind/lua_include.hpp>
27 #include <luabind/detail/stack_utils.hpp>
28 #include <luabind/detail/conversion_storage.hpp>
29 #include <luabind/luabind.hpp>
30 #include <luabind/exception_handler.hpp>
31 #include <luabind/get_main_thread.hpp>
34 using namespace luabind::detail
;
36 namespace luabind
{ namespace detail
38 LUABIND_API
int property_tag(lua_State
* L
)
40 lua_pushstring(L
, "luabind: property_tag function can't be called");
46 luabind::detail::class_rep::class_rep(type_id
const& type
52 , m_class_type(cpp_class
)
56 handle(L
, -1).swap(m_table
);
58 handle(L
, -1).swap(m_default_table
);
61 class_registry
* r
= class_registry::get_registry(L
);
62 assert((r
->cpp_class() != LUA_NOREF
) && "you must call luabind::open()");
64 lua_rawgeti(L
, LUA_REGISTRYINDEX
, r
->cpp_class());
65 lua_setmetatable(L
, -2);
67 lua_pushvalue(L
, -1); // duplicate our user data
70 m_instance_metatable
= r
->cpp_instance();
72 lua_pushstring(L
, "__luabind_cast_graph");
73 lua_gettable(L
, LUA_REGISTRYINDEX
);
74 m_casts
= static_cast<cast_graph
*>(lua_touserdata(L
, -1));
77 lua_pushstring(L
, "__luabind_class_id_map");
78 lua_gettable(L
, LUA_REGISTRYINDEX
);
79 m_classes
= static_cast<class_id_map
*>(lua_touserdata(L
, -1));
83 luabind::detail::class_rep::class_rep(lua_State
* L
, const char* name
)
84 : m_type(typeid(null_type
))
86 , m_class_type(lua_class
)
90 handle(L
, -1).swap(m_table
);
92 handle(L
, -1).swap(m_default_table
);
95 class_registry
* r
= class_registry::get_registry(L
);
96 assert((r
->cpp_class() != LUA_NOREF
) && "you must call luabind::open()");
98 lua_rawgeti(L
, LUA_REGISTRYINDEX
, r
->lua_class());
99 lua_setmetatable(L
, -2);
100 lua_pushvalue(L
, -1); // duplicate our user data
103 m_instance_metatable
= r
->lua_instance();
105 lua_pushstring(L
, "__luabind_cast_graph");
106 lua_gettable(L
, LUA_REGISTRYINDEX
);
107 m_casts
= static_cast<cast_graph
*>(lua_touserdata(L
, -1));
110 lua_pushstring(L
, "__luabind_class_id_map");
111 lua_gettable(L
, LUA_REGISTRYINDEX
);
112 m_classes
= static_cast<class_id_map
*>(lua_touserdata(L
, -1));
116 luabind::detail::class_rep::~class_rep()
120 // leaves object on lua stack
121 std::pair
<void*,void*>
122 luabind::detail::class_rep::allocate(lua_State
* L
) const
124 const int size
= sizeof(object_rep
);
125 char* mem
= static_cast<char*>(lua_newuserdata(L
, size
));
126 return std::pair
<void*,void*>(mem
, 0);
132 bool super_deprecation_disabled
= false;
134 } // namespace unnamed
136 // this is called as metamethod __call on the class_rep.
137 int luabind::detail::class_rep::constructor_dispatcher(lua_State
* L
)
139 class_rep
* cls
= static_cast<class_rep
*>(lua_touserdata(L
, 1));
141 int args
= lua_gettop(L
);
143 push_new_instance(L
, cls
);
148 lua_rawgeti(L
, LUA_REGISTRYINDEX
, cls
->metatable_ref());
149 lua_setmetatable(L
, -2);
151 if (super_deprecation_disabled
152 && cls
->get_class_type() == class_rep::lua_class
153 && !cls
->bases().empty())
155 lua_pushstring(L
, "super");
157 lua_pushvalue(L
, -3);
158 lua_pushcclosure(L
, super_callback
, 2);
159 lua_settable(L
, LUA_GLOBALSINDEX
);
162 lua_pushvalue(L
, -1);
166 lua_pushliteral(L
, "__init");
174 lua_call(L
, args
, 0);
176 if (super_deprecation_disabled
)
178 lua_pushstring(L
, "super");
180 lua_settable(L
, LUA_GLOBALSINDEX
);
186 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info
& binfo
)
188 // If you hit this assert you are deriving from a type that is not registered
189 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
190 // Please note that if you don't need to have access to the base class or the
191 // conversion from the derived class to the base class, you don't need
192 // to tell luabind that it derives.
193 assert(binfo
.base
&& "You cannot derive from an unregistered type");
195 class_rep
* bcrep
= binfo
.base
;
197 // import all static constants
198 for (std::map
<const char*, int, ltstr
>::const_iterator i
= bcrep
->m_static_constants
.begin();
199 i
!= bcrep
->m_static_constants
.end(); ++i
)
201 int& v
= m_static_constants
[i
->first
];
205 // also, save the baseclass info to be used for typecasts
206 m_bases
.push_back(binfo
);
209 LUABIND_API
void luabind::disable_super_deprecation()
211 super_deprecation_disabled
= true;
214 int luabind::detail::class_rep::super_callback(lua_State
* L
)
216 int args
= lua_gettop(L
);
218 class_rep
* crep
= static_cast<class_rep
*>(lua_touserdata(L
, lua_upvalueindex(1)));
219 class_rep
* base
= crep
->bases()[0].base
;
221 if (base
->bases().empty())
223 lua_pushstring(L
, "super");
225 lua_settable(L
, LUA_GLOBALSINDEX
);
229 lua_pushstring(L
, "super");
230 lua_pushlightuserdata(L
, base
);
231 lua_pushvalue(L
, lua_upvalueindex(2));
232 lua_pushcclosure(L
, super_callback
, 2);
233 lua_settable(L
, LUA_GLOBALSINDEX
);
237 lua_pushstring(L
, "__init");
242 lua_pushvalue(L
, lua_upvalueindex(2));
245 lua_call(L
, args
+ 1, 0);
247 // TODO: instead of clearing the global variable "super"
248 // store it temporarily in the registry. maybe we should
249 // have some kind of warning if the super global is used?
250 lua_pushstring(L
, "super");
252 lua_settable(L
, LUA_GLOBALSINDEX
);
259 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State
* L
)
261 class_rep
* crep
= static_cast<class_rep
*>(lua_touserdata(L
, 1));
267 lua_pushvalue(L
, -3);
268 lua_pushvalue(L
, -3);
274 crep
->get_default_table(L
);
278 crep
->m_operator_cache
= 0; // invalidate cache
288 int luabind::detail::class_rep::static_class_gettable(lua_State
* L
)
290 class_rep
* crep
= static_cast<class_rep
*>(lua_touserdata(L
, 1));
292 // look in the static function table
293 crep
->get_default_table(L
);
296 if (!lua_isnil(L
, -1)) return 1;
299 const char* key
= lua_tostring(L
, 2);
301 if (std::strlen(key
) != lua_strlen(L
, 2))
307 std::map
<const char*, int, ltstr
>::const_iterator j
= crep
->m_static_constants
.find(key
);
309 if (j
!= crep
->m_static_constants
.end())
311 lua_pushnumber(L
, j
->second
);
315 #ifndef LUABIND_NO_ERROR_CHECKING
318 std::string msg
= "no static '";
320 msg
+= "' in class '";
323 lua_pushstring(L
, msg
.c_str());
334 bool luabind::detail::is_class_rep(lua_State
* L
, int index
)
336 if (lua_getmetatable(L
, index
) == 0) return false;
338 lua_pushstring(L
, "__luabind_classrep");
340 if (lua_toboolean(L
, -1))
350 void luabind::detail::finalize(lua_State
* L
, class_rep
* crep
)
352 if (crep
->get_class_type() != class_rep::lua_class
) return;
354 // lua_pushvalue(L, -1); // copy the object ref
356 lua_pushliteral(L
, "__finalize");
360 if (lua_isnil(L
, -1))
366 lua_pushvalue(L
, -2);
370 for (std::vector
<class_rep::base_info
>::const_iterator
371 i
= crep
->bases().begin(); i
!= crep
->bases().end(); ++i
)
373 if (i
->base
) finalize(L
, i
->base
);
377 void luabind::detail::class_rep::cache_operators(lua_State
* L
)
379 m_operator_cache
= 0x1;
381 for (int i
= 0; i
< number_of_operators
; ++i
)
384 lua_pushstring(L
, get_operator_name(i
));
387 if (lua_isfunction(L
, -1)) m_operator_cache
|= 1 << (i
+ 1);
393 bool luabind::detail::class_rep::has_operator_in_lua(lua_State
* L
, int id
)
395 if ((m_operator_cache
& 0x1) == 0)
398 const int mask
= 1 << (id
+ 1);
400 return (m_operator_cache
& mask
) != 0;