Rewrite construction code to always just call __init().
[luabind.git] / src / class_rep.cpp
blobbdfa2de0f94f65cab756ae94acd732169712ab32
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 #include <luabind/lua_include.hpp>
25 #include <luabind/detail/stack_utils.hpp>
26 #include <luabind/detail/conversion_storage.hpp>
27 #include <luabind/luabind.hpp>
28 #include <luabind/exception_handler.hpp>
29 #include <utility>
31 using namespace luabind::detail;
33 #ifndef LUABIND_NO_ERROR_CHECKING
35 std::string luabind::detail::get_overload_signatures_candidates(
36 lua_State* L
37 , std::vector<const overload_rep_base*>::iterator start
38 , std::vector<const overload_rep_base*>::iterator end
39 , std::string name)
41 std::string s;
42 for (; start != end; ++start)
44 s += name;
45 (*start)->get_signature(L, s);
46 s += "\n";
48 return s;
51 #endif
54 luabind::detail::class_rep::class_rep(LUABIND_TYPE_INFO type
55 , const char* name
56 , lua_State* L
57 , void(*destructor)(void*)
58 , void(*const_holder_destructor)(void*)
59 , LUABIND_TYPE_INFO holder_type
60 , LUABIND_TYPE_INFO const_holder_type
61 , void*(*extractor)(void*)
62 , const void*(*const_extractor)(void*)
63 , void(*const_converter)(void*,void*)
64 , void(*construct_holder)(void*,void*)
65 , void(*construct_const_holder)(void*,void*)
66 , void(*default_construct_holder)(void*)
67 , void(*default_construct_const_holder)(void*)
68 , void(*adopt_fun)(void*)
69 , int holder_size
70 , int holder_alignment)
72 : m_type(type)
73 , m_holder_type(holder_type)
74 , m_const_holder_type(const_holder_type)
75 , m_extractor(extractor)
76 , m_const_extractor(const_extractor)
77 , m_const_converter(const_converter)
78 , m_construct_holder(construct_holder)
79 , m_construct_const_holder(construct_const_holder)
80 , m_default_construct_holder(default_construct_holder)
81 , m_default_construct_const_holder(default_construct_const_holder)
82 , m_adopt_fun(adopt_fun)
83 , m_holder_size(holder_size)
84 , m_holder_alignment(holder_alignment)
85 , m_name(name)
86 , m_class_type(cpp_class)
87 , m_destructor(destructor)
88 , m_const_holder_destructor(const_holder_destructor)
89 , m_operator_cache(0)
91 assert(m_holder_alignment >= 1 && "internal error");
93 lua_newtable(L);
94 handle(L, -1).swap(m_table);
95 lua_newtable(L);
96 handle(L, -1).swap(m_default_table);
97 lua_pop(L, 2);
99 class_registry* r = class_registry::get_registry(L);
100 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
102 detail::getref(L, r->cpp_class());
103 lua_setmetatable(L, -2);
105 lua_pushvalue(L, -1); // duplicate our user data
106 m_self_ref.set(L);
108 m_instance_metatable = r->cpp_instance();
111 luabind::detail::class_rep::class_rep(lua_State* L, const char* name)
112 : m_type(LUABIND_INVALID_TYPE_INFO)
113 , m_holder_type(LUABIND_INVALID_TYPE_INFO)
114 , m_const_holder_type(LUABIND_INVALID_TYPE_INFO)
115 , m_extractor(0)
116 , m_const_extractor(0)
117 , m_const_converter(0)
118 , m_construct_holder(0)
119 , m_construct_const_holder(0)
120 , m_default_construct_holder(0)
121 , m_default_construct_const_holder(0)
122 , m_adopt_fun(0)
123 , m_holder_size(0)
124 , m_holder_alignment(1)
125 , m_name(name)
126 , m_class_type(lua_class)
127 , m_destructor(0)
128 , m_const_holder_destructor(0)
129 , m_operator_cache(0)
131 lua_newtable(L);
132 handle(L, -1).swap(m_table);
133 lua_newtable(L);
134 handle(L, -1).swap(m_default_table);
135 lua_pop(L, 2);
137 class_registry* r = class_registry::get_registry(L);
138 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
140 detail::getref(L, r->lua_class());
141 lua_setmetatable(L, -2);
142 lua_pushvalue(L, -1); // duplicate our user data
143 m_self_ref.set(L);
145 m_instance_metatable = r->lua_instance();
148 luabind::detail::class_rep::~class_rep()
152 // leaves object on lua stack
153 std::pair<void*,void*>
154 luabind::detail::class_rep::allocate(lua_State* L) const
156 const int overlap = sizeof(object_rep)&(m_holder_alignment-1);
157 const int padding = overlap==0?0:m_holder_alignment-overlap;
158 const int size = sizeof(object_rep) + padding + m_holder_size;
160 char* mem = static_cast<char*>(lua_newuserdata(L, size));
161 char* ptr = mem + sizeof(object_rep) + padding;
163 return std::pair<void*,void*>(mem,ptr);
166 void luabind::detail::class_rep::adopt(bool const_obj, void* obj)
168 if (m_adopt_fun == 0) return;
170 if (m_extractor)
172 assert(m_const_extractor);
173 if (const_obj)
174 m_adopt_fun(const_cast<void*>(m_const_extractor(obj)));
175 else
176 m_adopt_fun(m_extractor(obj));
178 else
180 m_adopt_fun(obj);
184 // lua stack: userdata, key
185 int luabind::detail::class_rep::gettable(lua_State* L)
187 // if key is nil, return nil
188 if (lua_isnil(L, 2))
190 lua_pushnil(L);
191 return 1;
194 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
196 // we have to ignore the first argument since this may point to
197 // a method that is not present in this class (but in a subclass)
198 const char* key = lua_tostring(L, 2);
200 #ifndef LUABIND_NO_ERROR_CHECKING
202 if (std::strlen(key) != lua_strlen(L, 2))
205 std::string msg("luabind does not support "
206 "member names with extra nulls:\n");
207 msg += std::string(lua_tostring(L, 2), lua_strlen(L, 2));
208 lua_pushstring(L, msg.c_str());
210 lua_error(L);
213 #endif
215 // special case to see if this is a null-pointer
216 if (key && !std::strcmp(key, "__ok"))
218 class_rep* crep = obj->crep();
220 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
221 : obj->ptr();
223 lua_pushboolean(L, p != 0);
224 return 1;
227 // First, look in the instance's table
228 detail::lua_reference const& tbl = obj->get_lua_table();
229 if (tbl.is_valid())
231 tbl.get(L);
232 lua_pushvalue(L, 2);
233 lua_gettable(L, -2);
234 if (!lua_isnil(L, -1))
236 lua_remove(L, -2); // remove table
237 return 1;
239 lua_pop(L, 2);
242 // Then look in the class' table for this member
243 obj->crep()->get_table(L);
244 lua_pushvalue(L, 2);
245 lua_gettable(L, -2);
247 if (!lua_isnil(L, -1))
249 lua_remove(L, -2); // remove table
250 return 1;
252 lua_pop(L, 2);
254 std::map<const char*, callback, ltstr>::iterator j = m_getters.find(key);
255 if (j != m_getters.end())
257 // the name is a data member
258 return j->second.func(L, j->second.pointer_offset);
261 lua_pushnil(L);
262 return 1;
265 // called from the metamethod for __newindex
266 // the object pointer is passed on the lua stack
267 // lua stack: userdata, key, value
268 bool luabind::detail::class_rep::settable(lua_State* L)
270 // if the key is 'nil' fail
271 if (lua_isnil(L, 2)) return false;
273 // we have to ignore the first argument since this may point to
274 // a method that is not present in this class (but in a subclass)
276 const char* key = lua_tostring(L, 2);
278 if (std::strlen(key) == lua_strlen(L, 2))
280 std::map<const char*, callback, ltstr>::iterator j = m_setters.find(key);
281 if (j != m_setters.end())
283 // the name is a data member
284 #ifndef LUABIND_NO_ERROR_CHECKING
285 if (j->second.match(L, 3) < 0)
287 std::string msg("the attribute '");
288 msg += m_name;
289 msg += ".";
290 msg += key;
291 msg += "' is of type: ";
292 j->second.sig(L, msg);
293 msg += "\nand does not match: (";
294 msg += stack_content_by_name(L, 3);
295 msg += ")";
296 lua_pushstring(L, msg.c_str());
297 return false;
299 #endif
300 j->second.func(L, j->second.pointer_offset);
301 return true;
304 if (m_getters.find(key) != m_getters.end())
306 // this means that we have a getter but no
307 // setter for an attribute. We will then fail
308 // because that attribute is read-only
309 std::string msg("the attribute '");
310 msg += m_name;
311 msg += ".";
312 msg += key;
313 msg += "' is read only";
314 lua_pushstring(L, msg.c_str());
315 return false;
319 // set the attribute to the object's table
320 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
321 detail::lua_reference& tbl = obj->get_lua_table();
322 if (!tbl.is_valid())
324 // this is the first time we are trying to add
325 // a member to this instance, create the table.
326 lua_newtable(L);
327 lua_pushvalue(L, -1);
328 tbl.set(L);
330 else
332 tbl.get(L);
334 lua_pushvalue(L, 2);
335 lua_pushvalue(L, 3);
336 lua_settable(L, 4);
337 lua_pop(L, 3);
338 return true;
341 int class_rep::gettable_dispatcher(lua_State* L)
343 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
344 return obj->crep()->gettable(L);
347 // this is called as __newindex metamethod on every instance of this class
348 int luabind::detail::class_rep::settable_dispatcher(lua_State* L)
350 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
352 bool success = obj->crep()->settable(L);
354 #ifndef LUABIND_NO_ERROR_CHECKING
356 if (!success)
358 // class_rep::settable() will leave
359 // error message on the stack in case
360 // of failure
361 lua_error(L);
364 #endif
366 return 0;
370 int luabind::detail::class_rep::operator_dispatcher(lua_State* L)
372 for (int i = 0; i < 2; ++i)
374 if (is_class_object(L, 1 + i))
376 int nargs = lua_gettop(L);
378 lua_pushvalue(L, lua_upvalueindex(1));
379 lua_gettable(L, 1 + i);
381 if (lua_isnil(L, -1))
383 lua_pop(L, 1);
384 continue;
387 lua_insert(L, 1); // move the function to the bottom
389 nargs = lua_toboolean(L, lua_upvalueindex(2)) ? 1 : nargs;
391 if (lua_toboolean(L, lua_upvalueindex(2))) // remove trailing nil
392 lua_remove(L, 3);
394 lua_call(L, nargs, 1);
395 return 1;
399 lua_pop(L, lua_gettop(L));
400 lua_pushstring(L, "No such operator defined");
401 lua_error(L);
403 return 0;
406 // this is called as metamethod __call on the class_rep.
407 int luabind::detail::class_rep::constructor_dispatcher(lua_State* L)
409 class_rep* cls = static_cast<class_rep*>(lua_touserdata(L, 1));
411 int args = lua_gettop(L);
413 lua_newtable(L);
414 lua_reference ref;
415 ref.set(L);
417 void* obj_ptr;
418 void* held_storage;
420 int flags = object_rep::lua_class | object_rep::owner;
422 boost::tie(obj_ptr, held_storage) = cls->allocate(L);
423 (new(obj_ptr) object_rep(cls, flags, ref))->set_object(held_storage);
425 detail::getref(L, cls->metatable_ref());
426 lua_setmetatable(L, -2);
428 lua_pushvalue(L, -1);
429 lua_replace(L, 1);
431 cls->get_table(L);
432 lua_pushstring(L, "__init");
433 lua_gettable(L, -2);
435 lua_insert(L, 1);
437 lua_pop(L, 1);
438 lua_insert(L, 1);
440 lua_call(L, args, 0);
442 return 1;
445 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo)
447 // If you hit this assert you are deriving from a type that is not registered
448 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
449 // Please note that if you don't need to have access to the base class or the
450 // conversion from the derived class to the base class, you don't need
451 // to tell luabind that it derives.
452 assert(binfo.base && "You cannot derive from an unregistered type");
454 class_rep* bcrep = binfo.base;
456 // import all getters from the base
457 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_getters.begin();
458 i != bcrep->m_getters.end(); ++i)
460 callback& m = m_getters[i->first];
461 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
462 m.func = i->second.func;
464 #ifndef LUABIND_NO_ERROR_CHECKING
465 m.match = i->second.match;
466 m.sig = i->second.sig;
467 #endif
470 // import all setters from the base
471 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_setters.begin();
472 i != bcrep->m_setters.end(); ++i)
474 callback& m = m_setters[i->first];
475 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
476 m.func = i->second.func;
478 #ifndef LUABIND_NO_ERROR_CHECKING
479 m.match = i->second.match;
480 m.sig = i->second.sig;
481 #endif
484 // import all static constants
485 for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin();
486 i != bcrep->m_static_constants.end(); ++i)
488 int& v = m_static_constants[i->first];
489 v = i->second;
492 // import all operators
493 for (int i = 0; i < number_of_operators; ++i)
495 for (std::vector<operator_callback>::const_iterator j = bcrep->m_operators[i].begin();
496 j != bcrep->m_operators[i].end(); ++j)
497 m_operators[i].push_back(*j);
500 // also, save the baseclass info to be used for typecasts
501 m_bases.push_back(binfo);
503 if (!m_destructor)
504 m_destructor = bcrep->m_destructor;
507 int luabind::detail::class_rep::super_callback(lua_State* L)
509 int args = lua_gettop(L);
511 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, lua_upvalueindex(2)));
512 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
513 class_rep* base = crep->bases()[0].base;
515 if (base->bases().empty())
517 obj->set_flags(obj->flags() & ~object_rep::call_super);
519 lua_pushstring(L, "super");
520 lua_pushnil(L);
521 lua_settable(L, LUA_GLOBALSINDEX);
523 else
525 lua_pushstring(L, "super");
526 lua_pushlightuserdata(L, base);
527 lua_pushvalue(L, lua_upvalueindex(2));
528 lua_pushcclosure(L, super_callback, 2);
529 lua_settable(L, LUA_GLOBALSINDEX);
532 base->get_table(L);
533 lua_pushstring(L, "__init");
534 lua_gettable(L, -2);
535 lua_insert(L, 1);
536 lua_pop(L, 1);
538 lua_pushvalue(L, lua_upvalueindex(2));
539 lua_insert(L, 2);
541 lua_call(L, args + 1, 0);
543 // TODO: instead of clearing the global variable "super"
544 // store it temporarily in the registry. maybe we should
545 // have some kind of warning if the super global is used?
546 lua_pushstring(L, "super");
547 lua_pushnil(L);
548 lua_settable(L, LUA_GLOBALSINDEX);
550 return 0;
555 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L)
557 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
559 // get first table
560 crep->get_table(L);
562 // copy key, value
563 lua_pushvalue(L, -3);
564 lua_pushvalue(L, -3);
565 lua_rawset(L, -3);
566 // pop table
567 lua_pop(L, 1);
569 // get default table
570 crep->get_default_table(L);
571 lua_replace(L, 1);
572 lua_rawset(L, -3);
574 crep->m_operator_cache = 0; // invalidate cache
576 return 0;
579 int luabind::detail::class_rep::construct_lua_class_callback(lua_State* L)
581 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
583 int args = lua_gettop(L);
585 // lua stack: crep <arguments>
587 lua_newtable(L);
588 detail::lua_reference ref;
589 ref.set(L);
591 bool has_bases = !crep->bases().empty();
593 if (has_bases)
595 lua_pushstring(L, "super");
596 lua_pushvalue(L, 1); // crep
599 // lua stack: crep <arguments> "super" crep
600 // or
601 // lua stack: crep <arguments>
603 // if we have a baseclass we set the flag to say that the super has not yet been called
604 // we will use this flag later to check that it actually was called from __init()
605 int flags = object_rep::lua_class | object_rep::owner | (has_bases ? object_rep::call_super : 0);
607 // void* obj_ptr = lua_newuserdata(L, sizeof(object_rep));
608 void* obj_ptr;
609 void* held_storage;
611 boost::tie(obj_ptr, held_storage) = crep->allocate(L);
612 (new(obj_ptr) object_rep(crep, flags, ref))->set_object(held_storage);
614 detail::getref(L, crep->metatable_ref());
615 lua_setmetatable(L, -2);
617 // lua stack: crep <arguments> "super" crep obj_ptr
618 // or
619 // lua stack: crep <arguments> obj_ptr
621 if (has_bases) lua_pushvalue(L, -1); // obj_ptr
622 lua_replace(L, 1); // obj_ptr
624 // lua stack: obj_ptr <arguments> "super" crep obj_ptr
625 // or
626 // lua stack: obj_ptr <arguments>
628 if (has_bases)
630 lua_pushcclosure(L, super_callback, 2);
631 // lua stack: crep <arguments> "super" function
632 lua_settable(L, LUA_GLOBALSINDEX);
635 // lua stack: crep <arguments>
637 lua_pushvalue(L, 1);
638 lua_insert(L, 1);
640 crep->get_table(L);
641 lua_pushstring(L, "__init");
642 lua_gettable(L, -2);
644 #ifndef LUABIND_NO_ERROR_CHECKING
646 // TODO: should this be a run-time error?
647 // maybe the default behavior should be to just call
648 // the base calss' constructor. We should register
649 // the super callback funktion as __init
650 if (!lua_isfunction(L, -1))
653 std::string msg = crep->name();
654 msg += ":__init is not defined";
655 lua_pushstring(L, msg.c_str());
657 lua_error(L);
660 #endif
662 lua_insert(L, 2); // function first on stack
663 lua_pop(L, 1);
664 // TODO: lua_call may invoke longjump! make sure we don't have any memory leaks!
665 // we don't have any stack objects here
666 lua_call(L, args, 0);
668 return 1;
671 // called from the metamethod for __index
672 // obj is the object pointer
673 int luabind::detail::class_rep::lua_class_gettable(lua_State* L)
675 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
676 class_rep* crep = obj->crep();
678 // we have to ignore the first argument since this may point to
679 // a method that is not present in this class (but in a subclass)
681 // BUG: This might catch members called "__ok\0foobar"
682 const char* key = lua_tostring(L, 2);
684 if (key && !std::strcmp(key, "__ok"))
686 class_rep* crep = obj->crep();
688 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
689 : obj->ptr();
691 lua_pushboolean(L, p != 0);
692 return 1;
695 // first look in the instance's table
696 detail::lua_reference const& tbl = obj->get_lua_table();
697 assert(tbl.is_valid());
698 tbl.get(L);
699 lua_pushvalue(L, 2);
700 lua_gettable(L, -2);
701 if (!lua_isnil(L, -1))
703 lua_remove(L, -2); // remove table
704 return 1;
706 lua_pop(L, 2);
708 // then look in the class' table
709 crep->get_table(L);
710 lua_pushvalue(L, 2);
711 lua_gettable(L, -2);
713 if (!lua_isnil(L, -1))
715 lua_remove(L, -2); // more table
716 return 1;
719 lua_pop(L, 2);
721 if (lua_isnil(L, 2))
723 lua_pushnil(L);
724 return 1;
727 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_getters.find(key);
728 if (j != crep->m_getters.end())
730 // the name is a data member
731 return j->second.func(L, j->second.pointer_offset);
734 lua_pushnil(L);
735 return 1;
738 // called from the metamethod for __newindex
739 // obj is the object pointer
740 int luabind::detail::class_rep::lua_class_settable(lua_State* L)
742 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
743 class_rep* crep = obj->crep();
745 // we have to ignore the first argument since this may point to
746 // a method that is not present in this class (but in a subclass)
747 // BUG: This will not work with keys with extra nulls in them
748 const char* key = lua_tostring(L, 2);
751 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_setters.find(key);
753 // if the strlen(key) is not the true length,
754 // it means that the member-name contains
755 // extra nulls. luabind does not support such
756 // names as member names. So, use the lua
757 // table as fall-back
758 if (j == crep->m_setters.end()
759 || std::strlen(key) != lua_strlen(L, 2))
761 std::map<const char*, class_rep::callback, ltstr>::iterator k = crep->m_getters.find(key);
763 #ifndef LUABIND_NO_ERROR_CHECKING
765 if (k != crep->m_getters.end())
768 std::string msg = "cannot set property '";
769 msg += crep->name();
770 msg += ".";
771 msg += key;
772 msg += "', because it's read only";
773 lua_pushstring(L, msg.c_str());
775 lua_error(L);
778 #endif
780 detail::lua_reference const& tbl = obj->get_lua_table();
781 assert(tbl.is_valid());
782 tbl.get(L);
783 lua_replace(L, 1);
784 lua_settable(L, 1);
786 else
788 // the name is a data member
789 j->second.func(L, j->second.pointer_offset);
792 return 0;
796 stack:
797 1: class_rep
798 2: member name
800 int luabind::detail::class_rep::static_class_gettable(lua_State* L)
802 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
804 // look in the static function table
805 crep->get_default_table(L);
806 lua_pushvalue(L, 2);
807 lua_gettable(L, -2);
808 if (!lua_isnil(L, -1)) return 1;
809 else lua_pop(L, 2);
811 const char* key = lua_tostring(L, 2);
813 if (std::strlen(key) != lua_strlen(L, 2))
815 lua_pushnil(L);
816 return 1;
819 std::map<const char*, int, ltstr>::const_iterator j = crep->m_static_constants.find(key);
821 if (j != crep->m_static_constants.end())
823 lua_pushnumber(L, j->second);
824 return 1;
827 #ifndef LUABIND_NO_ERROR_CHECKING
830 std::string msg = "no static '";
831 msg += key;
832 msg += "' in class '";
833 msg += crep->name();
834 msg += "'";
835 lua_pushstring(L, msg.c_str());
837 lua_error(L);
839 #endif
841 lua_pushnil(L);
843 return 1;
846 bool luabind::detail::is_class_rep(lua_State* L, int index)
848 if (lua_getmetatable(L, index) == 0) return false;
850 lua_pushstring(L, "__luabind_classrep");
851 lua_gettable(L, -2);
852 if (lua_toboolean(L, -1))
854 lua_pop(L, 2);
855 return true;
858 lua_pop(L, 2);
859 return false;
862 void luabind::detail::finalize(lua_State* L, class_rep* crep)
864 if (crep->get_class_type() != class_rep::lua_class) return;
866 // lua_pushvalue(L, -1); // copy the object ref
867 crep->get_table(L);
868 lua_pushstring(L, "__finalize");
869 lua_gettable(L, -2);
870 lua_remove(L, -2);
872 if (lua_isnil(L, -1))
874 lua_pop(L, 1);
876 else
878 lua_pushvalue(L, -2);
879 lua_call(L, 1, 0);
882 for (std::vector<class_rep::base_info>::const_iterator
883 i = crep->bases().begin(); i != crep->bases().end(); ++i)
885 if (i->base) finalize(L, i->base);
889 void* luabind::detail::class_rep::convert_to(
890 LUABIND_TYPE_INFO target_type
891 , const object_rep* obj
892 , conversion_storage& storage) const
894 // TODO: since this is a member function, we don't have to use the accesor functions for
895 // the types and the extractor
897 assert(obj == 0 || obj->crep() == this);
899 int steps = 0;
900 int offset = 0;
901 if (!(LUABIND_TYPE_INFO_EQUAL(holder_type(), target_type))
902 && !(LUABIND_TYPE_INFO_EQUAL(const_holder_type(), target_type)))
904 steps = implicit_cast(this, target_type, offset);
907 // should never be called with a type that can't be cast
908 assert((steps >= 0) && "internal error, please report");
910 if (LUABIND_TYPE_INFO_EQUAL(target_type, holder_type()))
912 if (obj == 0)
914 // we are trying to convert nil to a holder type
915 m_default_construct_holder(&storage.data);
916 storage.destructor = m_destructor;
917 return &storage.data;
919 // if the type we are trying to convert to is the holder_type
920 // it means that his crep has a holder_type (since it would have
921 // been invalid otherwise, and T cannot be invalid). It also means
922 // that we need no conversion, since the holder_type is what the
923 // object points to.
924 return obj->ptr();
927 if (LUABIND_TYPE_INFO_EQUAL(target_type, const_holder_type()))
929 if (obj == 0)
931 // we are trying to convert nil to a const holder type
932 m_default_construct_const_holder(&storage.data);
933 storage.destructor = m_const_holder_destructor;
934 return &storage.data;
937 if (obj->flags() & object_rep::constant)
939 // we are holding a constant
940 return obj->ptr();
942 else
944 // we are holding a non-constant, we need to convert it
945 // to a const_holder.
946 m_const_converter(obj->ptr(), &storage.data);
947 storage.destructor = m_const_holder_destructor;
948 return &storage.data;
952 void* raw_pointer;
954 if (has_holder())
956 assert(obj);
957 // this means that we have a holder type where the
958 // raw-pointer needs to be extracted
959 raw_pointer = extractor()(obj->ptr());
961 else
963 if (obj == 0) raw_pointer = 0;
964 else raw_pointer = obj->ptr();
967 return static_cast<char*>(raw_pointer) + offset;
970 void luabind::detail::class_rep::cache_operators(lua_State* L)
972 m_operator_cache = 0x1;
974 for (int i = 0; i < number_of_operators; ++i)
976 get_table(L);
977 lua_pushstring(L, get_operator_name(i));
978 lua_rawget(L, -2);
980 if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1);
982 lua_pop(L, 2);
986 bool luabind::detail::class_rep::has_operator_in_lua(lua_State* L, int id)
988 if ((m_operator_cache & 0x1) == 0)
989 cache_operators(L);
991 const int mask = 1 << (id + 1);
993 return (m_operator_cache & mask) != 0;
996 const class_rep::property_map& luabind::detail::class_rep::properties() const
998 return m_getters;