* fixed #47. Added dummy return.
[luabind.git] / src / class_rep.cpp
blobda4927521a25b9b7c5f3d886a7edd7cc0d182db6
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/luabind.hpp>
27 #include <utility>
29 using namespace luabind::detail;
31 namespace luabind { namespace detail
33 struct method_name
35 method_name(char const* n): name(n) {}
36 bool operator()(method_rep const& o) const
37 { return std::strcmp(o.name, name) == 0; }
38 char const* name;
43 #ifndef LUABIND_NO_ERROR_CHECKING
45 std::string luabind::detail::get_overload_signatures_candidates(
46 lua_State* L
47 , std::vector<const overload_rep_base*>::iterator start
48 , std::vector<const overload_rep_base*>::iterator end
49 , std::string name)
51 std::string s;
52 for (; start != end; ++start)
54 s += name;
55 (*start)->get_signature(L, s);
56 s += "\n";
58 return s;
61 #endif
64 luabind::detail::class_rep::class_rep(LUABIND_TYPE_INFO type
65 , const char* name
66 , lua_State* L
67 , void(*destructor)(void*)
68 , void(*const_holder_destructor)(void*)
69 , LUABIND_TYPE_INFO holder_type
70 , LUABIND_TYPE_INFO const_holder_type
71 , void*(*extractor)(void*)
72 , const void*(*const_extractor)(void*)
73 , void(*const_converter)(void*,void*)
74 , void(*construct_holder)(void*,void*)
75 , void(*construct_const_holder)(void*,void*)
76 , void(*default_construct_holder)(void*)
77 , void(*default_construct_const_holder)(void*)
78 , void(*adopt_fun)(void*)
79 , int holder_size
80 , int holder_alignment)
82 : m_type(type)
83 , m_holder_type(holder_type)
84 , m_const_holder_type(const_holder_type)
85 , m_extractor(extractor)
86 , m_const_extractor(const_extractor)
87 , m_const_converter(const_converter)
88 , m_construct_holder(construct_holder)
89 , m_construct_const_holder(construct_const_holder)
90 , m_default_construct_holder(default_construct_holder)
91 , m_default_construct_const_holder(default_construct_const_holder)
92 , m_adopt_fun(adopt_fun)
93 , m_holder_size(holder_size)
94 , m_holder_alignment(holder_alignment)
95 , m_name(name)
96 , m_class_type(cpp_class)
97 , m_destructor(destructor)
98 , m_const_holder_destructor(const_holder_destructor)
99 , m_operator_cache(0)
101 assert(m_holder_alignment >= 1 && "internal error");
103 lua_newtable(L);
104 handle(L, -1).swap(m_table);
105 lua_newtable(L);
106 handle(L, -1).swap(m_default_table);
107 lua_pop(L, 2);
109 class_registry* r = class_registry::get_registry(L);
110 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
112 detail::getref(L, r->cpp_class());
113 lua_setmetatable(L, -2);
115 lua_pushvalue(L, -1); // duplicate our user data
116 m_self_ref.set(L);
118 m_instance_metatable = r->cpp_instance();
121 luabind::detail::class_rep::class_rep(lua_State* L, const char* name)
122 : m_type(LUABIND_INVALID_TYPE_INFO)
123 , m_holder_type(LUABIND_INVALID_TYPE_INFO)
124 , m_const_holder_type(LUABIND_INVALID_TYPE_INFO)
125 , m_extractor(0)
126 , m_const_extractor(0)
127 , m_const_converter(0)
128 , m_construct_holder(0)
129 , m_construct_const_holder(0)
130 , m_default_construct_holder(0)
131 , m_default_construct_const_holder(0)
132 , m_adopt_fun(0)
133 , m_holder_size(0)
134 , m_holder_alignment(1)
135 , m_name(name)
136 , m_class_type(lua_class)
137 , m_destructor(0)
138 , m_const_holder_destructor(0)
139 , m_operator_cache(0)
141 lua_newtable(L);
142 handle(L, -1).swap(m_table);
143 lua_newtable(L);
144 handle(L, -1).swap(m_default_table);
145 lua_pop(L, 2);
147 class_registry* r = class_registry::get_registry(L);
148 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
150 detail::getref(L, r->lua_class());
151 lua_setmetatable(L, -2);
152 lua_pushvalue(L, -1); // duplicate our user data
153 m_self_ref.set(L);
155 m_instance_metatable = r->lua_instance();
158 luabind::detail::class_rep::~class_rep()
162 // leaves object on lua stack
163 std::pair<void*,void*>
164 luabind::detail::class_rep::allocate(lua_State* L) const
166 const int overlap = sizeof(object_rep)&(m_holder_alignment-1);
167 const int padding = overlap==0?0:m_holder_alignment-overlap;
168 const int size = sizeof(object_rep) + padding + m_holder_size;
170 char* mem = static_cast<char*>(lua_newuserdata(L, size));
171 char* ptr = mem + sizeof(object_rep) + padding;
173 return std::pair<void*,void*>(mem,ptr);
176 #include <iostream>
177 namespace
179 void dump_stack(lua_State* L)
181 for (int i = 1; i <= lua_gettop(L); ++i)
183 int t = lua_type(L, i);
184 switch (t)
186 case LUA_TNUMBER:
187 std::cout << "[" << i << "] number: " << lua_tonumber(L, i) << "\n";
188 break;
189 case LUA_TSTRING:
190 std::cout << "[" << i << "] string: " << lua_tostring(L, i) << "\n";
191 break;
192 case LUA_TUSERDATA:
193 std::cout << "[" << i << "] userdata: " << lua_touserdata(L, i) << "\n";
194 break;
195 case LUA_TTABLE:
196 std::cout << "[" << i << "] table:\n";
197 break;
198 case LUA_TNIL:
199 std::cout << "[" << i << "] nil:\n";
200 break;
207 void luabind::detail::class_rep::adopt(bool const_obj, void* obj)
209 if (m_adopt_fun == 0) return;
211 if (m_extractor)
213 assert(m_const_extractor);
214 if (const_obj)
215 m_adopt_fun(const_cast<void*>(m_const_extractor(obj)));
216 else
217 m_adopt_fun(m_extractor(obj));
219 else
221 m_adopt_fun(obj);
225 // lua stack: userdata, key
226 int luabind::detail::class_rep::gettable(lua_State* L)
228 // if key is nil, return nil
229 if (lua_isnil(L, 2))
231 lua_pushnil(L);
232 return 1;
235 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
237 // we have to ignore the first argument since this may point to
238 // a method that is not present in this class (but in a subclass)
239 const char* key = lua_tostring(L, 2);
241 #ifndef LUABIND_NO_ERROR_CHECKING
243 if (std::strlen(key) != lua_strlen(L, 2))
246 std::string msg("luabind does not support "
247 "member names with extra nulls:\n");
248 msg += std::string(lua_tostring(L, 2), lua_strlen(L, 2));
249 lua_pushstring(L, msg.c_str());
251 lua_error(L);
254 #endif
256 // special case to see if this is a null-pointer
257 if (key && !std::strcmp(key, "__ok"))
259 class_rep* crep = obj->crep();
261 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
262 : obj->ptr();
264 lua_pushboolean(L, p != 0);
265 return 1;
268 // First, look in the instance's table
269 detail::lua_reference const& tbl = obj->get_lua_table();
270 if (tbl.is_valid())
272 tbl.get(L);
273 lua_pushvalue(L, 2);
274 lua_gettable(L, -2);
275 if (!lua_isnil(L, -1))
277 lua_remove(L, -2); // remove table
278 return 1;
280 lua_pop(L, 2);
283 // Then look in the class' table for this member
284 obj->crep()->get_table(L);
285 lua_pushvalue(L, 2);
286 lua_gettable(L, -2);
288 if (!lua_isnil(L, -1))
290 lua_remove(L, -2); // remove table
291 return 1;
293 lua_pop(L, 2);
295 std::map<const char*, callback, ltstr>::iterator j = m_getters.find(key);
296 if (j != m_getters.end())
298 // the name is a data member
299 return j->second.func(L, j->second.pointer_offset);
302 lua_pushnil(L);
303 return 1;
306 // called from the metamethod for __newindex
307 // the object pointer is passed on the lua stack
308 // lua stack: userdata, key, value
309 bool luabind::detail::class_rep::settable(lua_State* L)
311 // if the key is 'nil' fail
312 if (lua_isnil(L, 2)) return false;
314 // we have to ignore the first argument since this may point to
315 // a method that is not present in this class (but in a subclass)
317 const char* key = lua_tostring(L, 2);
319 if (std::strlen(key) == lua_strlen(L, 2))
321 std::map<const char*, callback, ltstr>::iterator j = m_setters.find(key);
322 if (j != m_setters.end())
324 // the name is a data member
325 #ifndef LUABIND_NO_ERROR_CHECKING
326 if (j->second.match(L, 3) < 0)
328 std::string msg("the attribute '");
329 msg += m_name;
330 msg += ".";
331 msg += key;
332 msg += "' is of type: ";
333 j->second.sig(L, msg);
334 msg += "\nand does not match: (";
335 msg += stack_content_by_name(L, 3);
336 msg += ")";
337 lua_pushstring(L, msg.c_str());
338 return false;
340 #endif
341 j->second.func(L, j->second.pointer_offset);
342 return true;
345 if (m_getters.find(key) != m_getters.end())
347 // this means that we have a getter but no
348 // setter for an attribute. We will then fail
349 // because that attribute is read-only
350 std::string msg("the attribute '");
351 msg += m_name;
352 msg += ".";
353 msg += key;
354 msg += "' is read only";
355 lua_pushstring(L, msg.c_str());
356 return false;
360 // set the attribute to the object's table
361 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
362 detail::lua_reference& tbl = obj->get_lua_table();
363 if (!tbl.is_valid())
365 // this is the first time we are trying to add
366 // a member to this instance, create the table.
367 lua_newtable(L);
368 lua_pushvalue(L, -1);
369 tbl.set(L);
371 else
373 tbl.get(L);
375 lua_pushvalue(L, 2);
376 lua_pushvalue(L, 3);
377 lua_settable(L, 4);
378 lua_pop(L, 3);
379 return true;
382 int class_rep::gettable_dispatcher(lua_State* L)
384 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
385 return obj->crep()->gettable(L);
388 // this is called as __newindex metamethod on every instance of this class
389 int luabind::detail::class_rep::settable_dispatcher(lua_State* L)
391 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
393 bool success = obj->crep()->settable(L);
395 #ifndef LUABIND_NO_ERROR_CHECKING
397 if (!success)
399 // class_rep::settable() will leave
400 // error message on the stack in case
401 // of failure
402 lua_error(L);
405 #endif
407 return 0;
411 int luabind::detail::class_rep::operator_dispatcher(lua_State* L)
413 for (int i = 0; i < 2; ++i)
415 if (is_class_object(L, 1 + i))
417 int nargs = lua_gettop(L);
419 lua_pushvalue(L, lua_upvalueindex(1));
420 lua_gettable(L, 1 + i);
422 if (lua_isnil(L, -1))
424 lua_pop(L, 1);
425 continue;
428 lua_insert(L, 1); // move the function to the bottom
430 nargs = lua_toboolean(L, lua_upvalueindex(2)) ? 1 : nargs;
432 if (lua_toboolean(L, lua_upvalueindex(2))) // remove trailing nil
433 lua_remove(L, 3);
435 lua_call(L, nargs, 1);
436 return 1;
440 lua_pop(L, lua_gettop(L));
441 lua_pushstring(L, "No such operator defined");
442 lua_error(L);
444 return 0;
447 // this is called as metamethod __call on the class_rep.
448 int luabind::detail::class_rep::constructor_dispatcher(lua_State* L)
450 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
451 construct_rep* rep = &crep->m_constructor;
453 bool ambiguous = false;
454 int match_index = -1;
455 int min_match = std::numeric_limits<int>::max();
456 bool found;
458 #ifdef LUABIND_NO_ERROR_CHECKING
460 if (rep->overloads.size() == 1)
462 match_index = 0;
464 else
467 #endif
469 int num_params = lua_gettop(L) - 1;
470 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
472 #ifdef LUABIND_NO_ERROR_CHECKING
475 #else
477 if (!found)
480 std::string msg("no constructor of '");
481 msg += crep->name();
482 msg += "' matched the arguments (";
483 msg += stack_content_by_name(L, 2);
484 msg += ")\n candidates are:\n";
486 msg += get_overload_signatures(L, rep->overloads.begin(), rep->overloads.end(), crep->name());
488 lua_pushstring(L, msg.c_str());
490 lua_error(L);
492 else if (ambiguous)
495 std::string msg("call of overloaded constructor '");
496 msg += crep->m_name;
497 msg += "(";
498 msg += stack_content_by_name(L, 2);
499 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
501 std::vector<const overload_rep_base*> candidates;
502 find_exact_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), min_match, num_params, candidates);
503 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), crep->name());
505 lua_pushstring(L, msg.c_str());
507 lua_error(L);
510 #endif
512 #ifndef LUABIND_NO_EXCEPTIONS
517 #endif
518 void* obj_rep;
519 void* held;
521 boost::tie(obj_rep,held) = crep->allocate(L);
523 weak_ref backref(L, -1);
525 void* object_ptr = rep->overloads[match_index].construct(L, backref);
527 if (crep->has_holder())
529 crep->m_construct_holder(held, object_ptr);
530 object_ptr = held;
532 new(obj_rep) object_rep(object_ptr, crep, object_rep::owner, crep->destructor());
534 detail::getref(L, crep->m_instance_metatable);
535 lua_setmetatable(L, -2);
536 return 1;
538 #ifndef LUABIND_NO_EXCEPTIONS
542 catch(const error&)
545 catch(const std::exception& e)
547 lua_pushstring(L, e.what());
549 catch(const char* s)
551 lua_pushstring(L, s);
553 catch(...)
556 std::string msg = crep->name();
557 msg += "() threw an exception";
558 lua_pushstring(L, msg.c_str());
562 // we can only reach this line if an exception was thrown
563 lua_error(L);
564 return 0; // will never be reached
566 #endif
571 the functions dispatcher assumes the following:
573 upvalues:
574 1: method_rep* method, points to the method_rep that this dispatcher is to call
575 2: boolean force_static, is true if this is to be a static call
576 and false if it is a normal call (= virtual if possible).
578 stack:
579 1: object_rep* self, points to the object the call is being made on
582 int luabind::detail::class_rep::function_dispatcher(lua_State* L)
584 #ifndef NDEBUG
586 /* lua_Debug tmp_;
587 assert(lua_getinfo(L, "u", &tmp_));
588 assert(tmp_.nups == 2);*/
589 assert(lua_type(L, lua_upvalueindex(1)) == LUA_TLIGHTUSERDATA);
590 assert(lua_type(L, lua_upvalueindex(2)) == LUA_TBOOLEAN);
591 assert(lua_type(L, lua_upvalueindex(3)) == LUA_TLIGHTUSERDATA);
592 assert(lua_touserdata(L, lua_upvalueindex(3)) == reinterpret_cast<void*>(0x1337));
596 // assert(lua_type(L, 1) == LUA_TUSERDATA);
598 #endif
600 method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
601 int force_static_call = lua_toboolean(L, lua_upvalueindex(2));
603 bool ambiguous = false;
604 int match_index = -1;
605 int min_match = std::numeric_limits<int>::max();
606 bool found;
608 #ifdef LUABIND_NO_ERROR_CHECKING
609 if (rep->overloads().size() == 1)
611 match_index = 0;
613 else
615 #endif
617 int num_params = lua_gettop(L) /*- 1*/;
618 found = find_best_match(L, &rep->overloads().front(), rep->overloads().size()
619 , sizeof(overload_rep), ambiguous, min_match, match_index, num_params);
621 #ifdef LUABIND_NO_ERROR_CHECKING
625 #else
627 if (!found)
630 std::string msg = "no overload of '";
631 msg += rep->crep->name();
632 msg += ":";
633 msg += rep->name;
634 msg += "' matched the arguments (";
635 msg += stack_content_by_name(L, 1);
636 msg += ")\ncandidates are:\n";
638 std::string function_name;
639 function_name += rep->crep->name();
640 function_name += ":";
641 function_name += rep->name;
643 msg += get_overload_signatures(L, rep->overloads().begin()
644 , rep->overloads().end(), function_name);
646 lua_pushstring(L, msg.c_str());
648 lua_error(L);
650 else if (ambiguous)
653 std::string msg = "call of overloaded '";
654 msg += rep->crep->name();
655 msg += ":";
656 msg += rep->name;
657 msg += "(";
658 msg += stack_content_by_name(L, 1);
659 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
661 std::vector<const overload_rep_base*> candidates;
662 find_exact_match(L, &rep->overloads().front(), rep->overloads().size()
663 , sizeof(overload_rep), min_match, num_params, candidates);
665 std::string function_name;
666 function_name += rep->crep->name();
667 function_name += ":";
668 function_name += rep->name;
670 msg += get_overload_signatures_candidates(L, candidates.begin()
671 , candidates.end(), function_name);
673 lua_pushstring(L, msg.c_str());
675 lua_error(L);
678 #endif
680 #ifndef LUABIND_NO_EXCEPTIONS
685 #endif
687 const overload_rep& o = rep->overloads()[match_index];
689 if (force_static_call && !o.has_static())
691 lua_pushstring(L, "pure virtual function called");
693 else
695 return o.call(L, force_static_call != 0);
698 #ifndef LUABIND_NO_EXCEPTIONS
701 catch(const error&)
704 catch(const std::exception& e)
706 lua_pushstring(L, e.what());
708 catch (const char* s)
710 lua_pushstring(L, s);
712 catch(...)
714 std::string msg = rep->crep->name();
715 msg += ":";
716 msg += rep->name;
717 msg += "() threw an exception";
718 lua_pushstring(L, msg.c_str());
721 #endif
723 // we can only reach this line if an error occured
724 lua_error(L);
725 return 0; // will never be reached
728 #ifndef NDEBUG
730 #ifndef BOOST_NO_STRINGSTREAM
731 #include <sstream>
732 #else
733 #include <strstream>
734 #endif
736 namespace
738 std::string to_string(luabind::object const& o)
740 using namespace luabind;
741 if (type(o) == LUA_TSTRING) return object_cast<std::string>(o);
742 lua_State* L = o.interpreter();
743 LUABIND_CHECK_STACK(L);
745 #ifdef BOOST_NO_STRINGSTREAM
746 std::strstream s;
747 #else
748 std::stringstream s;
749 #endif
751 if (type(o) == LUA_TNUMBER)
753 s << object_cast<float>(o);
754 return s.str();
757 s << "<" << lua_typename(L, type(o)) << ">";
758 #ifdef BOOST_NO_STRINGSTREAM
759 s << std::ends;
760 #endif
761 return s.str();
765 std::string member_to_string(luabind::object const& e)
767 #if !defined(LUABIND_NO_ERROR_CHECKING)
768 using namespace luabind;
769 lua_State* L = e.interpreter();
770 LUABIND_CHECK_STACK(L);
772 if (type(e) == LUA_TFUNCTION)
774 e.push(L);
775 detail::stack_pop p(L, 1);
778 if (lua_getupvalue(L, -1, 3) == 0) return to_string(e);
779 detail::stack_pop p2(L, 1);
780 if (lua_touserdata(L, -1) != reinterpret_cast<void*>(0x1337)) return to_string(e);
783 #ifdef BOOST_NO_STRINGSTREAM
784 std::strstream s;
785 #else
786 std::stringstream s;
787 #endif
789 lua_getupvalue(L, -1, 2);
790 detail::stack_pop p2(L, 1);
791 int b = lua_toboolean(L, -1);
792 s << "<c++ function";
793 if (b) s << " (default)";
794 s << "> ";
798 lua_getupvalue(L, -1, 1);
799 detail::stack_pop p2(L, 1);
800 method_rep* m = static_cast<method_rep*>(lua_touserdata(L, -1));
801 s << m << "\n";
802 for (std::vector<overload_rep>::const_iterator i = m->overloads().begin();
803 i != m->overloads().end(); ++i)
805 std::string str;
806 i->get_signature(L, str);
807 s << " " << str << "\n";
810 #ifdef BOOST_NO_STRINGSTREAM
811 s << std::ends;
812 #endif
813 return s.str();
816 return to_string(e);
817 #else
818 return "";
819 #endif
823 std::string luabind::detail::class_rep::class_info_string(lua_State* L) const
825 #ifdef BOOST_NO_STRINGSTREAM
826 std::strstream ret;
827 #else
828 std::stringstream ret;
829 #endif
831 ret << "CLASS: " << m_name << "\n";
833 ret << "dynamic dispatch functions:\n------------------\n";
835 for (luabind::iterator i(m_table), end; i != end; ++i)
837 luabind::object e = *i;
838 ret << " " << to_string(i.key()) << ": " << member_to_string(e) << "\n";
841 ret << "default implementations:\n------------------\n";
843 for (luabind::iterator i(m_default_table), end; i != end; ++i)
845 luabind::object e = *i;
846 ret << " " << to_string(i.key()) << ": " << member_to_string(e) << "\n";
848 #ifdef BOOST_NO_STRINGSTREAM
849 ret << std::ends;
850 #endif
851 return ret.str();
853 #endif
855 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo)
857 // If you hit this assert you are deriving from a type that is not registered
858 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
859 // Please note that if you don't need to have access to the base class or the
860 // conversion from the derived class to the base class, you don't need
861 // to tell luabind that it derives.
862 assert(binfo.base && "You cannot derive from an unregistered type");
864 class_rep* bcrep = binfo.base;
866 // import all functions from the base
867 typedef std::list<detail::method_rep> methods_t;
869 for (methods_t::const_iterator i = bcrep->m_methods.begin();
870 i != bcrep->m_methods.end(); ++i)
872 add_method(*i);
875 // import all getters from the base
876 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_getters.begin();
877 i != bcrep->m_getters.end(); ++i)
879 callback& m = m_getters[i->first];
880 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
881 m.func = i->second.func;
883 #ifndef LUABIND_NO_ERROR_CHECKING
884 m.match = i->second.match;
885 m.sig = i->second.sig;
886 #endif
889 // import all setters from the base
890 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_setters.begin();
891 i != bcrep->m_setters.end(); ++i)
893 callback& m = m_setters[i->first];
894 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
895 m.func = i->second.func;
897 #ifndef LUABIND_NO_ERROR_CHECKING
898 m.match = i->second.match;
899 m.sig = i->second.sig;
900 #endif
903 // import all static constants
904 for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin();
905 i != bcrep->m_static_constants.end(); ++i)
907 int& v = m_static_constants[i->first];
908 v = i->second;
911 // import all operators
912 for (int i = 0; i < number_of_operators; ++i)
914 for (std::vector<operator_callback>::const_iterator j = bcrep->m_operators[i].begin();
915 j != bcrep->m_operators[i].end(); ++j)
916 m_operators[i].push_back(*j);
919 // also, save the baseclass info to be used for typecasts
920 m_bases.push_back(binfo);
923 int luabind::detail::class_rep::super_callback(lua_State* L)
925 int args = lua_gettop(L);
927 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, lua_upvalueindex(2)));
928 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
929 class_rep* base = crep->bases()[0].base;
931 if (base->get_class_type() == class_rep::lua_class)
933 if (base->bases().empty())
935 obj->set_flags(obj->flags() & ~object_rep::call_super);
937 lua_pushstring(L, "super");
938 lua_pushnil(L);
939 lua_settable(L, LUA_GLOBALSINDEX);
941 else
943 lua_pushstring(L, "super");
944 lua_pushlightuserdata(L, base);
945 lua_pushvalue(L, lua_upvalueindex(2));
946 lua_pushcclosure(L, super_callback, 2);
947 lua_settable(L, LUA_GLOBALSINDEX);
950 base->get_table(L);
951 lua_pushstring(L, "__init");
952 lua_gettable(L, -2);
953 lua_insert(L, 1);
954 lua_pop(L, 1);
956 lua_pushvalue(L, lua_upvalueindex(2));
957 lua_insert(L, 2);
959 lua_call(L, args + 1, 0);
961 // TODO: instead of clearing the global variable "super"
962 // store it temporarily in the registry. maybe we should
963 // have some kind of warning if the super global is used?
964 lua_pushstring(L, "super");
965 lua_pushnil(L);
966 lua_settable(L, LUA_GLOBALSINDEX);
968 else
970 obj->set_flags(obj->flags() & ~object_rep::call_super);
972 // we need to push some garbage at index 1 to make the construction work
973 lua_pushboolean(L, 1);
974 lua_insert(L, 1);
976 construct_rep* rep = &base->m_constructor;
978 bool ambiguous = false;
979 int match_index = -1;
980 int min_match = std::numeric_limits<int>::max();
981 bool found;
983 #ifdef LUABIND_NO_ERROR_CHECKING
985 if (rep->overloads.size() == 1)
987 match_index = 0;
989 else
992 #endif
994 int num_params = lua_gettop(L) - 1;
995 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
997 #ifdef LUABIND_NO_ERROR_CHECKING
1001 #else
1003 if (!found)
1006 std::string msg = "no constructor of '";
1007 msg += base->m_name;
1008 msg += "' matched the arguments (";
1009 msg += stack_content_by_name(L, 2);
1010 msg += ")";
1011 lua_pushstring(L, msg.c_str());
1013 lua_error(L);
1015 else if (ambiguous)
1018 std::string msg = "call of overloaded constructor '";
1019 msg += base->m_name;
1020 msg += "(";
1021 msg += stack_content_by_name(L, 2);
1022 msg += ")' is ambiguous";
1023 lua_pushstring(L, msg.c_str());
1025 lua_error(L);
1028 // TODO: should this be a warning or something?
1030 // since the derived class is a lua class
1031 // it may have reimplemented virtual functions
1032 // therefore, we have to instantiate the Basewrapper
1033 // if there is no basewrapper, throw a run-time error
1034 if (!rep->overloads[match_index].has_wrapped_construct())
1037 std::string msg = "Cannot derive from C++ class '";
1038 msg += base->name();
1039 msg += "'. It does not have a wrapped type";
1040 lua_pushstring(L, msg.c_str());
1042 lua_error(L);
1045 #endif
1047 #ifndef LUABIND_NO_EXCEPTIONS
1052 #endif
1053 lua_pushvalue(L, lua_upvalueindex(2));
1054 weak_ref backref(L, -1);
1055 lua_pop(L, 1);
1057 void* storage_ptr = obj->ptr();
1059 if (!rep->overloads[match_index].has_wrapped_construct())
1061 // if the type doesn't have a wrapped type, use the ordinary constructor
1062 void* instance = rep->overloads[match_index].construct(L, backref);
1064 if (crep->has_holder())
1066 crep->m_construct_holder(storage_ptr, instance);
1068 else
1070 obj->set_object(instance);
1073 else
1075 // get reference to lua object
1076 /* lua_pushvalue(L, lua_upvalueindex(2));
1077 detail::lua_reference ref;
1078 ref.set(L);
1079 void* instance = rep->overloads[match_index].construct_wrapped(L, ref);*/
1081 void* instance = rep->overloads[match_index].construct_wrapped(L, backref);
1083 if (crep->has_holder())
1085 crep->m_construct_holder(storage_ptr, instance);
1087 else
1089 obj->set_object(instance);
1092 // TODO: is the wrapped type destructed correctly?
1093 // it should, since the destructor is either the wrapped type's
1094 // destructor or the base type's destructor, depending on wether
1095 // the type has a wrapped type or not.
1096 obj->set_destructor(base->destructor());
1097 return 0;
1099 #ifndef LUABIND_NO_EXCEPTIONS
1102 catch(const error&)
1105 catch(const std::exception& e)
1107 lua_pushstring(L, e.what());
1109 catch(const char* s)
1111 lua_pushstring(L, s);
1113 catch(...)
1115 std::string msg = base->m_name;
1116 msg += "() threw an exception";
1117 lua_pushstring(L, msg.c_str());
1119 // can only be reached if an exception was thrown
1120 lua_error(L);
1121 #endif
1124 return 0;
1130 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L)
1132 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1134 // get first table
1135 crep->get_table(L);
1137 // copy key, value
1138 lua_pushvalue(L, -3);
1139 lua_pushvalue(L, -3);
1140 lua_rawset(L, -3);
1141 // pop table
1142 lua_pop(L, 1);
1144 // get default table
1145 crep->get_default_table(L);
1146 lua_replace(L, 1);
1147 lua_rawset(L, -3);
1149 crep->m_operator_cache = 0; // invalidate cache
1151 return 0;
1154 int luabind::detail::class_rep::construct_lua_class_callback(lua_State* L)
1156 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1158 int args = lua_gettop(L);
1160 // lua stack: crep <arguments>
1162 lua_newtable(L);
1163 detail::lua_reference ref;
1164 ref.set(L);
1166 bool has_bases = !crep->bases().empty();
1168 if (has_bases)
1170 lua_pushstring(L, "super");
1171 lua_pushvalue(L, 1); // crep
1174 // lua stack: crep <arguments> "super" crep
1175 // or
1176 // lua stack: crep <arguments>
1178 // if we have a baseclass we set the flag to say that the super has not yet been called
1179 // we will use this flag later to check that it actually was called from __init()
1180 int flags = object_rep::lua_class | object_rep::owner | (has_bases ? object_rep::call_super : 0);
1182 // void* obj_ptr = lua_newuserdata(L, sizeof(object_rep));
1183 void* obj_ptr;
1184 void* held_storage;
1186 boost::tie(obj_ptr, held_storage) = crep->allocate(L);
1187 (new(obj_ptr) object_rep(crep, flags, ref))->set_object(held_storage);
1189 detail::getref(L, crep->metatable_ref());
1190 lua_setmetatable(L, -2);
1192 // lua stack: crep <arguments> "super" crep obj_ptr
1193 // or
1194 // lua stack: crep <arguments> obj_ptr
1196 if (has_bases) lua_pushvalue(L, -1); // obj_ptr
1197 lua_replace(L, 1); // obj_ptr
1199 // lua stack: obj_ptr <arguments> "super" crep obj_ptr
1200 // or
1201 // lua stack: obj_ptr <arguments>
1203 if (has_bases)
1205 lua_pushcclosure(L, super_callback, 2);
1206 // lua stack: crep <arguments> "super" function
1207 lua_settable(L, LUA_GLOBALSINDEX);
1210 // lua stack: crep <arguments>
1212 lua_pushvalue(L, 1);
1213 lua_insert(L, 1);
1215 crep->get_table(L);
1216 lua_pushstring(L, "__init");
1217 lua_gettable(L, -2);
1219 #ifndef LUABIND_NO_ERROR_CHECKING
1221 // TODO: should this be a run-time error?
1222 // maybe the default behavior should be to just call
1223 // the base calss' constructor. We should register
1224 // the super callback funktion as __init
1225 if (!lua_isfunction(L, -1))
1228 std::string msg = crep->name();
1229 msg += ":__init is not defined";
1230 lua_pushstring(L, msg.c_str());
1232 lua_error(L);
1235 #endif
1237 lua_insert(L, 2); // function first on stack
1238 lua_pop(L, 1);
1239 // TODO: lua_call may invoke longjump! make sure we don't have any memory leaks!
1240 // we don't have any stack objects here
1241 lua_call(L, args, 0);
1243 #ifndef LUABIND_NO_ERROR_CHECKING
1245 object_rep* obj = static_cast<object_rep*>(obj_ptr);
1246 if (obj->flags() & object_rep::call_super)
1248 lua_pushstring(L, "derived class must call super on base");
1249 lua_error(L);
1252 #endif
1254 return 1;
1257 // called from the metamethod for __index
1258 // obj is the object pointer
1259 int luabind::detail::class_rep::lua_class_gettable(lua_State* L)
1261 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1262 class_rep* crep = obj->crep();
1264 #ifndef LUABIND_NO_ERROR_CHECKING
1266 if (obj->flags() & object_rep::call_super)
1268 lua_pushstring(L, "derived class must call super on base");
1269 lua_error(L);
1272 #endif
1274 // we have to ignore the first argument since this may point to
1275 // a method that is not present in this class (but in a subclass)
1277 // BUG: This might catch members called "__ok\0foobar"
1278 const char* key = lua_tostring(L, 2);
1280 if (key && !std::strcmp(key, "__ok"))
1282 class_rep* crep = obj->crep();
1284 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
1285 : obj->ptr();
1287 lua_pushboolean(L, p != 0);
1288 return 1;
1291 // first look in the instance's table
1292 detail::lua_reference const& tbl = obj->get_lua_table();
1293 assert(tbl.is_valid());
1294 tbl.get(L);
1295 lua_pushvalue(L, 2);
1296 lua_gettable(L, -2);
1297 if (!lua_isnil(L, -1))
1299 lua_remove(L, -2); // remove table
1300 return 1;
1302 lua_pop(L, 2);
1304 // then look in the class' table
1305 crep->get_table(L);
1306 lua_pushvalue(L, 2);
1307 lua_gettable(L, -2);
1309 if (!lua_isnil(L, -1))
1311 lua_remove(L, -2); // more table
1312 return 1;
1315 lua_pop(L, 2);
1317 if (lua_isnil(L, 2))
1319 lua_pushnil(L);
1320 return 1;
1323 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_getters.find(key);
1324 if (j != crep->m_getters.end())
1326 // the name is a data member
1327 return j->second.func(L, j->second.pointer_offset);
1330 lua_pushnil(L);
1331 return 1;
1334 // called from the metamethod for __newindex
1335 // obj is the object pointer
1336 int luabind::detail::class_rep::lua_class_settable(lua_State* L)
1338 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1339 class_rep* crep = obj->crep();
1341 #ifndef LUABIND_NO_ERROR_CHECKING
1343 if (obj->flags() & object_rep::call_super)
1345 // this block makes sure the std::string is destructed
1346 // before lua_error is called
1348 std::string msg = "derived class '";
1349 msg += crep->name();
1350 msg += "'must call super on base";
1351 lua_pushstring(L, msg.c_str());
1353 lua_error(L);
1356 #endif
1358 // we have to ignore the first argument since this may point to
1359 // a method that is not present in this class (but in a subclass)
1360 // BUG: This will not work with keys with extra nulls in them
1361 const char* key = lua_tostring(L, 2);
1364 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_setters.find(key);
1366 // if the strlen(key) is not the true length,
1367 // it means that the member-name contains
1368 // extra nulls. luabind does not support such
1369 // names as member names. So, use the lua
1370 // table as fall-back
1371 if (j == crep->m_setters.end()
1372 || std::strlen(key) != lua_strlen(L, 2))
1374 std::map<const char*, class_rep::callback, ltstr>::iterator k = crep->m_getters.find(key);
1376 #ifndef LUABIND_NO_ERROR_CHECKING
1378 if (k != crep->m_getters.end())
1381 std::string msg = "cannot set property '";
1382 msg += crep->name();
1383 msg += ".";
1384 msg += key;
1385 msg += "', because it's read only";
1386 lua_pushstring(L, msg.c_str());
1388 lua_error(L);
1391 #endif
1393 detail::lua_reference const& tbl = obj->get_lua_table();
1394 assert(tbl.is_valid());
1395 tbl.get(L);
1396 lua_replace(L, 1);
1397 lua_settable(L, 1);
1399 else
1401 // the name is a data member
1402 j->second.func(L, j->second.pointer_offset);
1405 return 0;
1409 stack:
1410 1: class_rep
1411 2: member name
1413 int luabind::detail::class_rep::static_class_gettable(lua_State* L)
1415 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1417 // look in the static function table
1418 crep->get_default_table(L);
1419 lua_pushvalue(L, 2);
1420 lua_gettable(L, -2);
1421 if (!lua_isnil(L, -1)) return 1;
1422 else lua_pop(L, 2);
1424 const char* key = lua_tostring(L, 2);
1426 if (std::strlen(key) != lua_strlen(L, 2))
1428 lua_pushnil(L);
1429 return 1;
1432 std::map<const char*, int, ltstr>::const_iterator j = crep->m_static_constants.find(key);
1434 if (j != crep->m_static_constants.end())
1436 lua_pushnumber(L, j->second);
1437 return 1;
1440 #ifndef LUABIND_NO_ERROR_CHECKING
1443 std::string msg = "no static '";
1444 msg += key;
1445 msg += "' in class '";
1446 msg += crep->name();
1447 msg += "'";
1448 lua_pushstring(L, msg.c_str());
1450 lua_error(L);
1452 #endif
1454 lua_pushnil(L);
1456 return 1;
1459 bool luabind::detail::is_class_rep(lua_State* L, int index)
1461 if (lua_getmetatable(L, index) == 0) return false;
1463 lua_pushstring(L, "__luabind_classrep");
1464 lua_gettable(L, -2);
1465 if (lua_toboolean(L, -1))
1467 lua_pop(L, 2);
1468 return true;
1471 lua_pop(L, 2);
1472 return false;
1475 void luabind::detail::finalize(lua_State* L, class_rep* crep)
1477 if (crep->get_class_type() != class_rep::lua_class) return;
1479 // lua_pushvalue(L, -1); // copy the object ref
1480 crep->get_table(L);
1481 lua_pushstring(L, "__finalize");
1482 lua_gettable(L, -2);
1483 lua_remove(L, -2);
1485 if (lua_isnil(L, -1))
1487 lua_pop(L, 1);
1489 else
1491 lua_pushvalue(L, -2);
1492 lua_call(L, 1, 0);
1495 for (std::vector<class_rep::base_info>::const_iterator
1496 i = crep->bases().begin(); i != crep->bases().end(); ++i)
1498 if (i->base) finalize(L, i->base);
1502 void* luabind::detail::class_rep::convert_to(
1503 LUABIND_TYPE_INFO target_type
1504 , const object_rep* obj
1505 , void* target_memory) const
1507 // TODO: since this is a member function, we don't have to use the accesor functions for
1508 // the types and the extractor
1510 assert(obj == 0 || obj->crep() == this);
1512 int steps = 0;
1513 int offset = 0;
1514 if (!(LUABIND_TYPE_INFO_EQUAL(holder_type(), target_type))
1515 && !(LUABIND_TYPE_INFO_EQUAL(const_holder_type(), target_type)))
1517 steps = implicit_cast(this, target_type, offset);
1520 // should never be called with a type that can't be cast
1521 assert((steps >= 0) && "internal error, please report");
1523 if (LUABIND_TYPE_INFO_EQUAL(target_type, holder_type()))
1525 if (obj == 0)
1527 // we are trying to convert nil to a holder type
1528 m_default_construct_holder(target_memory);
1529 return target_memory;
1531 // if the type we are trying to convert to is the holder_type
1532 // it means that his crep has a holder_type (since it would have
1533 // been invalid otherwise, and T cannot be invalid). It also means
1534 // that we need no conversion, since the holder_type is what the
1535 // object points to.
1536 return obj->ptr();
1539 if (LUABIND_TYPE_INFO_EQUAL(target_type, const_holder_type()))
1541 if (obj == 0)
1543 // we are trying to convert nil to a const holder type
1544 m_default_construct_const_holder(target_memory);
1545 return target_memory;
1548 if (obj->flags() & object_rep::constant)
1550 // we are holding a constant
1551 return obj->ptr();
1553 else
1555 // we are holding a non-constant, we need to convert it
1556 // to a const_holder.
1557 m_const_converter(obj->ptr(), target_memory);
1558 return target_memory;
1562 void* raw_pointer;
1564 if (has_holder())
1566 assert(obj);
1567 // this means that we have a holder type where the
1568 // raw-pointer needs to be extracted
1569 raw_pointer = extractor()(obj->ptr());
1571 else
1573 if (obj == 0) raw_pointer = 0;
1574 else raw_pointer = obj->ptr();
1577 return static_cast<char*>(raw_pointer) + offset;
1580 void luabind::detail::class_rep::cache_operators(lua_State* L)
1582 m_operator_cache = 0x1;
1584 for (int i = 0; i < number_of_operators; ++i)
1586 get_table(L);
1587 lua_pushstring(L, get_operator_name(i));
1588 lua_rawget(L, -2);
1590 if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1);
1592 lua_pop(L, 2);
1596 bool luabind::detail::class_rep::has_operator_in_lua(lua_State* L, int id)
1598 if ((m_operator_cache & 0x1) == 0)
1599 cache_operators(L);
1601 const int mask = 1 << (id + 1);
1603 return (m_operator_cache & mask) != 0;
1607 // this will merge all overloads of fun into the list of
1608 // overloads in this class
1609 void luabind::detail::class_rep::add_method(luabind::detail::method_rep const& fun)
1611 typedef std::list<detail::method_rep> methods_t;
1613 methods_t::iterator m = std::find_if(
1614 m_methods.begin()
1615 , m_methods.end()
1616 , method_name(fun.name));
1617 if (m == m_methods.end())
1619 m_methods.push_back(method_rep());
1620 m = m_methods.end();
1621 std::advance(m, -1);
1622 m->name = fun.name;
1624 m->crep = this;
1626 typedef std::vector<detail::overload_rep> overloads_t;
1628 for (overloads_t::const_iterator j = fun.overloads().begin();
1629 j != fun.overloads().end(); ++j)
1631 detail::overload_rep o = *j;
1632 m->add_overload(o);
1636 // this function will add all the overloads in method rep to
1637 // this class' lua tables. If there already are overloads with this
1638 // name, thses will simply be appended to the overload list
1639 void luabind::detail::class_rep::register_methods(lua_State* L)
1641 LUABIND_CHECK_STACK(L);
1642 // insert the function in the normal member table
1643 // and in the default member table
1644 m_default_table.push(L);
1645 m_table.push(L);
1647 // pops the tables
1648 detail::stack_pop pop_tables(L, 2);
1650 for (std::list<method_rep>::const_iterator m = m_methods.begin();
1651 m != m_methods.end(); ++m)
1653 // create the function closure in m_table
1654 lua_pushstring(L, m->name);
1655 lua_pushlightuserdata(L, const_cast<void*>((const void*)&(*m)));
1656 lua_pushboolean(L, 0);
1657 lua_pushlightuserdata(L, reinterpret_cast<void*>(0x1337));
1658 lua_pushcclosure(L, function_dispatcher, 3);
1659 lua_settable(L, -3);
1661 // create the function closure in m_default_table
1662 lua_pushstring(L, m->name);
1663 lua_pushlightuserdata(L, const_cast<void*>((const void*)&(*m)));
1664 lua_pushboolean(L, 1);
1665 lua_pushlightuserdata(L, reinterpret_cast<void*>(0x1337));
1666 lua_pushcclosure(L, function_dispatcher, 3);
1667 lua_settable(L, -4);
1671 const class_rep::property_map& luabind::detail::class_rep::properties() const
1673 return m_getters;