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>
33 using namespace luabind::detail
;
35 namespace luabind
{ namespace detail
37 LUABIND_API
int property_tag(lua_State
* L
)
39 lua_pushstring(L
, "luabind: property_tag function can't be called");
45 luabind::detail::class_rep::class_rep(type_id
const& type
51 , m_class_type(cpp_class
)
55 handle(L
, -1).swap(m_table
);
57 handle(L
, -1).swap(m_default_table
);
60 class_registry
* r
= class_registry::get_registry(L
);
61 assert((r
->cpp_class() != LUA_NOREF
) && "you must call luabind::open()");
63 lua_rawgeti(L
, LUA_REGISTRYINDEX
, r
->cpp_class());
64 lua_setmetatable(L
, -2);
66 lua_pushvalue(L
, -1); // duplicate our user data
69 m_instance_metatable
= r
->cpp_instance();
71 lua_pushstring(L
, "__luabind_cast_graph");
72 lua_gettable(L
, LUA_REGISTRYINDEX
);
73 m_casts
= static_cast<cast_graph
*>(lua_touserdata(L
, -1));
76 lua_pushstring(L
, "__luabind_class_id_map");
77 lua_gettable(L
, LUA_REGISTRYINDEX
);
78 m_classes
= static_cast<class_id_map
*>(lua_touserdata(L
, -1));
82 luabind::detail::class_rep::class_rep(lua_State
* L
, const char* name
)
83 : m_type(typeid(null_type
))
85 , m_class_type(lua_class
)
89 handle(L
, -1).swap(m_table
);
91 handle(L
, -1).swap(m_default_table
);
94 class_registry
* r
= class_registry::get_registry(L
);
95 assert((r
->cpp_class() != LUA_NOREF
) && "you must call luabind::open()");
97 lua_rawgeti(L
, LUA_REGISTRYINDEX
, r
->lua_class());
98 lua_setmetatable(L
, -2);
99 lua_pushvalue(L
, -1); // duplicate our user data
102 m_instance_metatable
= r
->lua_instance();
104 lua_pushstring(L
, "__luabind_cast_graph");
105 lua_gettable(L
, LUA_REGISTRYINDEX
);
106 m_casts
= static_cast<cast_graph
*>(lua_touserdata(L
, -1));
109 lua_pushstring(L
, "__luabind_class_id_map");
110 lua_gettable(L
, LUA_REGISTRYINDEX
);
111 m_classes
= static_cast<class_id_map
*>(lua_touserdata(L
, -1));
115 luabind::detail::class_rep::~class_rep()
119 // leaves object on lua stack
120 std::pair
<void*,void*>
121 luabind::detail::class_rep::allocate(lua_State
* L
) const
123 const int size
= sizeof(object_rep
);
124 char* mem
= static_cast<char*>(lua_newuserdata(L
, size
));
125 return std::pair
<void*,void*>(mem
, 0);
129 // this is called as metamethod __call on the class_rep.
130 int luabind::detail::class_rep::constructor_dispatcher(lua_State
* L
)
132 class_rep
* cls
= static_cast<class_rep
*>(lua_touserdata(L
, 1));
134 int args
= lua_gettop(L
);
136 push_new_instance(L
, cls
);
141 lua_rawgeti(L
, LUA_REGISTRYINDEX
, cls
->metatable_ref());
142 lua_setmetatable(L
, -2);
144 if (cls
->get_class_type() == class_rep::lua_class
145 && !cls
->bases().empty())
147 lua_pushstring(L
, "super");
149 lua_pushvalue(L
, -3);
150 lua_pushcclosure(L
, super_callback
, 2);
151 lua_settable(L
, LUA_GLOBALSINDEX
);
154 lua_pushvalue(L
, -1);
158 lua_pushstring(L
, "__init");
166 lua_call(L
, args
, 0);
171 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info
& binfo
)
173 // If you hit this assert you are deriving from a type that is not registered
174 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
175 // Please note that if you don't need to have access to the base class or the
176 // conversion from the derived class to the base class, you don't need
177 // to tell luabind that it derives.
178 assert(binfo
.base
&& "You cannot derive from an unregistered type");
180 class_rep
* bcrep
= binfo
.base
;
182 // import all static constants
183 for (std::map
<const char*, int, ltstr
>::const_iterator i
= bcrep
->m_static_constants
.begin();
184 i
!= bcrep
->m_static_constants
.end(); ++i
)
186 int& v
= m_static_constants
[i
->first
];
190 // also, save the baseclass info to be used for typecasts
191 m_bases
.push_back(binfo
);
197 bool super_deprecation_disabled
= false;
199 } // namespace unnamed
201 LUABIND_API
void luabind::disable_super_deprecation()
203 super_deprecation_disabled
= true;
206 int luabind::detail::class_rep::super_callback(lua_State
* L
)
208 if (!super_deprecation_disabled
)
211 "DEPRECATION: 'super' has been deprecated in favor of "
212 "directly calling the base class __init() function. "
213 "This error can be disabled by calling 'luabind::disable_super_deprecation()'."
218 int args
= lua_gettop(L
);
220 class_rep
* crep
= static_cast<class_rep
*>(lua_touserdata(L
, lua_upvalueindex(1)));
221 class_rep
* base
= crep
->bases()[0].base
;
223 if (base
->bases().empty())
225 lua_pushstring(L
, "super");
227 lua_settable(L
, LUA_GLOBALSINDEX
);
231 lua_pushstring(L
, "super");
232 lua_pushlightuserdata(L
, base
);
233 lua_pushvalue(L
, lua_upvalueindex(2));
234 lua_pushcclosure(L
, super_callback
, 2);
235 lua_settable(L
, LUA_GLOBALSINDEX
);
239 lua_pushstring(L
, "__init");
244 lua_pushvalue(L
, lua_upvalueindex(2));
247 lua_call(L
, args
+ 1, 0);
249 // TODO: instead of clearing the global variable "super"
250 // store it temporarily in the registry. maybe we should
251 // have some kind of warning if the super global is used?
252 lua_pushstring(L
, "super");
254 lua_settable(L
, LUA_GLOBALSINDEX
);
261 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State
* L
)
263 class_rep
* crep
= static_cast<class_rep
*>(lua_touserdata(L
, 1));
269 lua_pushvalue(L
, -3);
270 lua_pushvalue(L
, -3);
276 crep
->get_default_table(L
);
280 crep
->m_operator_cache
= 0; // invalidate cache
290 int luabind::detail::class_rep::static_class_gettable(lua_State
* L
)
292 class_rep
* crep
= static_cast<class_rep
*>(lua_touserdata(L
, 1));
294 // look in the static function table
295 crep
->get_default_table(L
);
298 if (!lua_isnil(L
, -1)) return 1;
301 const char* key
= lua_tostring(L
, 2);
303 if (std::strlen(key
) != lua_strlen(L
, 2))
309 std::map
<const char*, int, ltstr
>::const_iterator j
= crep
->m_static_constants
.find(key
);
311 if (j
!= crep
->m_static_constants
.end())
313 lua_pushnumber(L
, j
->second
);
317 #ifndef LUABIND_NO_ERROR_CHECKING
320 std::string msg
= "no static '";
322 msg
+= "' in class '";
325 lua_pushstring(L
, msg
.c_str());
336 bool luabind::detail::is_class_rep(lua_State
* L
, int index
)
338 if (lua_getmetatable(L
, index
) == 0) return false;
340 lua_pushstring(L
, "__luabind_classrep");
342 if (lua_toboolean(L
, -1))
352 void luabind::detail::finalize(lua_State
* L
, class_rep
* crep
)
354 if (crep
->get_class_type() != class_rep::lua_class
) return;
356 // lua_pushvalue(L, -1); // copy the object ref
358 lua_pushstring(L
, "__finalize");
362 if (lua_isnil(L
, -1))
368 lua_pushvalue(L
, -2);
372 for (std::vector
<class_rep::base_info
>::const_iterator
373 i
= crep
->bases().begin(); i
!= crep
->bases().end(); ++i
)
375 if (i
->base
) finalize(L
, i
->base
);
379 void luabind::detail::class_rep::cache_operators(lua_State
* L
)
381 m_operator_cache
= 0x1;
383 for (int i
= 0; i
< number_of_operators
; ++i
)
386 lua_pushstring(L
, get_operator_name(i
));
389 if (lua_isfunction(L
, -1)) m_operator_cache
|= 1 << (i
+ 1);
395 bool luabind::detail::class_rep::has_operator_in_lua(lua_State
* L
, int id
)
397 if ((m_operator_cache
& 0x1) == 0)
400 const int mask
= 1 << (id
+ 1);
402 return (m_operator_cache
& mask
) != 0;