Added __stdcall fix missing from previous commit.
[luabind.git] / src / class_rep.cpp
blobef0e8119e03f00122fc97909283412aab56c42a9
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;
463 found = true;
465 else
468 #endif
470 int num_params = lua_gettop(L) - 1;
471 overload_rep_base const* first =
472 rep->overloads.empty() ? 0 : &rep->overloads.front();
473 found = find_best_match(L, first, rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
475 #ifdef LUABIND_NO_ERROR_CHECKING
478 #else
480 if (!found)
483 std::string msg("no constructor of '");
484 msg += crep->name();
485 msg += "' matched the arguments (";
486 msg += stack_content_by_name(L, 2);
487 msg += ")\n candidates are:\n";
489 msg += get_overload_signatures(L, rep->overloads.begin(), rep->overloads.end(), crep->name());
491 lua_pushstring(L, msg.c_str());
493 lua_error(L);
495 else if (ambiguous)
498 std::string msg("call of overloaded constructor '");
499 msg += crep->m_name;
500 msg += "(";
501 msg += stack_content_by_name(L, 2);
502 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
504 std::vector<const overload_rep_base*> candidates;
505 find_exact_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), min_match, num_params, candidates);
506 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), crep->name());
508 lua_pushstring(L, msg.c_str());
510 lua_error(L);
513 #endif
515 #ifndef LUABIND_NO_EXCEPTIONS
520 #endif
521 void* obj_rep;
522 void* held;
524 boost::tie(obj_rep,held) = crep->allocate(L);
526 weak_ref backref(L, -1);
528 void* object_ptr = rep->overloads[match_index].construct(L, backref);
530 if (crep->has_holder())
532 crep->m_construct_holder(held, object_ptr);
533 object_ptr = held;
535 new(obj_rep) object_rep(object_ptr, crep, object_rep::owner, crep->destructor());
537 detail::getref(L, crep->m_instance_metatable);
538 lua_setmetatable(L, -2);
539 return 1;
541 #ifndef LUABIND_NO_EXCEPTIONS
545 catch(const error&)
548 catch(const std::exception& e)
550 lua_pushstring(L, e.what());
552 catch(const char* s)
554 lua_pushstring(L, s);
556 catch(...)
559 std::string msg = crep->name();
560 msg += "() threw an exception";
561 lua_pushstring(L, msg.c_str());
565 // we can only reach this line if an exception was thrown
566 lua_error(L);
567 return 0; // will never be reached
569 #endif
574 the functions dispatcher assumes the following:
576 upvalues:
577 1: method_rep* method, points to the method_rep that this dispatcher is to call
578 2: boolean force_static, is true if this is to be a static call
579 and false if it is a normal call (= virtual if possible).
581 stack:
582 1: object_rep* self, points to the object the call is being made on
585 int luabind::detail::class_rep::function_dispatcher(lua_State* L)
587 #ifndef NDEBUG
589 /* lua_Debug tmp_;
590 assert(lua_getinfo(L, "u", &tmp_));
591 assert(tmp_.nups == 2);*/
592 assert(lua_type(L, lua_upvalueindex(1)) == LUA_TLIGHTUSERDATA);
593 assert(lua_type(L, lua_upvalueindex(2)) == LUA_TBOOLEAN);
594 assert(lua_type(L, lua_upvalueindex(3)) == LUA_TLIGHTUSERDATA);
595 assert(lua_touserdata(L, lua_upvalueindex(3)) == reinterpret_cast<void*>(0x1337));
599 // assert(lua_type(L, 1) == LUA_TUSERDATA);
601 #endif
603 method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
604 int force_static_call = lua_toboolean(L, lua_upvalueindex(2));
606 bool ambiguous = false;
607 int match_index = -1;
608 int min_match = std::numeric_limits<int>::max();
609 bool found;
611 #ifdef LUABIND_NO_ERROR_CHECKING
612 if (rep->overloads().size() == 1)
614 match_index = 0;
616 else
618 #endif
620 int num_params = lua_gettop(L) /*- 1*/;
621 found = find_best_match(L, &rep->overloads().front(), rep->overloads().size()
622 , sizeof(overload_rep), ambiguous, min_match, match_index, num_params);
624 #ifdef LUABIND_NO_ERROR_CHECKING
628 #else
630 if (!found)
633 std::string msg = "no overload of '";
634 msg += rep->crep->name();
635 msg += ":";
636 msg += rep->name;
637 msg += "' matched the arguments (";
638 msg += stack_content_by_name(L, 1);
639 msg += ")\ncandidates are:\n";
641 std::string function_name;
642 function_name += rep->crep->name();
643 function_name += ":";
644 function_name += rep->name;
646 msg += get_overload_signatures(L, rep->overloads().begin()
647 , rep->overloads().end(), function_name);
649 lua_pushstring(L, msg.c_str());
651 lua_error(L);
653 else if (ambiguous)
656 std::string msg = "call of overloaded '";
657 msg += rep->crep->name();
658 msg += ":";
659 msg += rep->name;
660 msg += "(";
661 msg += stack_content_by_name(L, 1);
662 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
664 std::vector<const overload_rep_base*> candidates;
665 find_exact_match(L, &rep->overloads().front(), rep->overloads().size()
666 , sizeof(overload_rep), min_match, num_params, candidates);
668 std::string function_name;
669 function_name += rep->crep->name();
670 function_name += ":";
671 function_name += rep->name;
673 msg += get_overload_signatures_candidates(L, candidates.begin()
674 , candidates.end(), function_name);
676 lua_pushstring(L, msg.c_str());
678 lua_error(L);
681 #endif
683 #ifndef LUABIND_NO_EXCEPTIONS
688 #endif
690 const overload_rep& o = rep->overloads()[match_index];
692 if (force_static_call && !o.has_static())
694 lua_pushstring(L, "pure virtual function called");
696 else
698 return o.call(L, force_static_call != 0);
701 #ifndef LUABIND_NO_EXCEPTIONS
704 catch(const error&)
707 catch(const std::exception& e)
709 lua_pushstring(L, e.what());
711 catch (const char* s)
713 lua_pushstring(L, s);
715 catch(...)
717 std::string msg = rep->crep->name();
718 msg += ":";
719 msg += rep->name;
720 msg += "() threw an exception";
721 lua_pushstring(L, msg.c_str());
724 #endif
726 // we can only reach this line if an error occured
727 lua_error(L);
728 return 0; // will never be reached
731 #ifndef NDEBUG
733 #ifndef BOOST_NO_STRINGSTREAM
734 #include <sstream>
735 #else
736 #include <strstream>
737 #endif
739 namespace
741 std::string to_string(luabind::object const& o)
743 using namespace luabind;
744 if (type(o) == LUA_TSTRING) return object_cast<std::string>(o);
745 lua_State* L = o.interpreter();
746 LUABIND_CHECK_STACK(L);
748 #ifdef BOOST_NO_STRINGSTREAM
749 std::strstream s;
750 #else
751 std::stringstream s;
752 #endif
754 if (type(o) == LUA_TNUMBER)
756 s << object_cast<float>(o);
757 return s.str();
760 s << "<" << lua_typename(L, type(o)) << ">";
761 #ifdef BOOST_NO_STRINGSTREAM
762 s << std::ends;
763 #endif
764 return s.str();
768 std::string member_to_string(luabind::object const& e)
770 #if !defined(LUABIND_NO_ERROR_CHECKING)
771 using namespace luabind;
772 lua_State* L = e.interpreter();
773 LUABIND_CHECK_STACK(L);
775 if (type(e) == LUA_TFUNCTION)
777 e.push(L);
778 detail::stack_pop p(L, 1);
781 if (lua_getupvalue(L, -1, 3) == 0) return to_string(e);
782 detail::stack_pop p2(L, 1);
783 if (lua_touserdata(L, -1) != reinterpret_cast<void*>(0x1337)) return to_string(e);
786 #ifdef BOOST_NO_STRINGSTREAM
787 std::strstream s;
788 #else
789 std::stringstream s;
790 #endif
792 lua_getupvalue(L, -1, 2);
793 detail::stack_pop p2(L, 1);
794 int b = lua_toboolean(L, -1);
795 s << "<c++ function";
796 if (b) s << " (default)";
797 s << "> ";
801 lua_getupvalue(L, -1, 1);
802 detail::stack_pop p2(L, 1);
803 method_rep* m = static_cast<method_rep*>(lua_touserdata(L, -1));
804 s << m << "\n";
805 for (std::vector<overload_rep>::const_iterator i = m->overloads().begin();
806 i != m->overloads().end(); ++i)
808 std::string str;
809 i->get_signature(L, str);
810 s << " " << str << "\n";
813 #ifdef BOOST_NO_STRINGSTREAM
814 s << std::ends;
815 #endif
816 return s.str();
819 return to_string(e);
820 #else
821 return "";
822 #endif
826 std::string luabind::detail::class_rep::class_info_string(lua_State* L) const
828 #ifdef BOOST_NO_STRINGSTREAM
829 std::strstream ret;
830 #else
831 std::stringstream ret;
832 #endif
834 ret << "CLASS: " << m_name << "\n";
836 ret << "dynamic dispatch functions:\n------------------\n";
838 for (luabind::iterator i(m_table), end; i != end; ++i)
840 luabind::object e = *i;
841 ret << " " << to_string(i.key()) << ": " << member_to_string(e) << "\n";
844 ret << "default implementations:\n------------------\n";
846 for (luabind::iterator i(m_default_table), end; i != end; ++i)
848 luabind::object e = *i;
849 ret << " " << to_string(i.key()) << ": " << member_to_string(e) << "\n";
851 #ifdef BOOST_NO_STRINGSTREAM
852 ret << std::ends;
853 #endif
854 return ret.str();
856 #endif
858 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo)
860 // If you hit this assert you are deriving from a type that is not registered
861 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
862 // Please note that if you don't need to have access to the base class or the
863 // conversion from the derived class to the base class, you don't need
864 // to tell luabind that it derives.
865 assert(binfo.base && "You cannot derive from an unregistered type");
867 class_rep* bcrep = binfo.base;
869 // import all functions from the base
870 typedef std::list<detail::method_rep> methods_t;
872 for (methods_t::const_iterator i = bcrep->m_methods.begin();
873 i != bcrep->m_methods.end(); ++i)
875 add_method(*i);
878 // import all getters from the base
879 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_getters.begin();
880 i != bcrep->m_getters.end(); ++i)
882 callback& m = m_getters[i->first];
883 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
884 m.func = i->second.func;
886 #ifndef LUABIND_NO_ERROR_CHECKING
887 m.match = i->second.match;
888 m.sig = i->second.sig;
889 #endif
892 // import all setters from the base
893 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_setters.begin();
894 i != bcrep->m_setters.end(); ++i)
896 callback& m = m_setters[i->first];
897 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
898 m.func = i->second.func;
900 #ifndef LUABIND_NO_ERROR_CHECKING
901 m.match = i->second.match;
902 m.sig = i->second.sig;
903 #endif
906 // import all static constants
907 for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin();
908 i != bcrep->m_static_constants.end(); ++i)
910 int& v = m_static_constants[i->first];
911 v = i->second;
914 // import all operators
915 for (int i = 0; i < number_of_operators; ++i)
917 for (std::vector<operator_callback>::const_iterator j = bcrep->m_operators[i].begin();
918 j != bcrep->m_operators[i].end(); ++j)
919 m_operators[i].push_back(*j);
922 // also, save the baseclass info to be used for typecasts
923 m_bases.push_back(binfo);
926 int luabind::detail::class_rep::super_callback(lua_State* L)
928 int args = lua_gettop(L);
930 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, lua_upvalueindex(2)));
931 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
932 class_rep* base = crep->bases()[0].base;
934 if (base->get_class_type() == class_rep::lua_class)
936 if (base->bases().empty())
938 obj->set_flags(obj->flags() & ~object_rep::call_super);
940 lua_pushstring(L, "super");
941 lua_pushnil(L);
942 lua_settable(L, LUA_GLOBALSINDEX);
944 else
946 lua_pushstring(L, "super");
947 lua_pushlightuserdata(L, base);
948 lua_pushvalue(L, lua_upvalueindex(2));
949 lua_pushcclosure(L, super_callback, 2);
950 lua_settable(L, LUA_GLOBALSINDEX);
953 base->get_table(L);
954 lua_pushstring(L, "__init");
955 lua_gettable(L, -2);
956 lua_insert(L, 1);
957 lua_pop(L, 1);
959 lua_pushvalue(L, lua_upvalueindex(2));
960 lua_insert(L, 2);
962 lua_call(L, args + 1, 0);
964 // TODO: instead of clearing the global variable "super"
965 // store it temporarily in the registry. maybe we should
966 // have some kind of warning if the super global is used?
967 lua_pushstring(L, "super");
968 lua_pushnil(L);
969 lua_settable(L, LUA_GLOBALSINDEX);
971 else
973 obj->set_flags(obj->flags() & ~object_rep::call_super);
975 // we need to push some garbage at index 1 to make the construction work
976 lua_pushboolean(L, 1);
977 lua_insert(L, 1);
979 construct_rep* rep = &base->m_constructor;
981 bool ambiguous = false;
982 int match_index = -1;
983 int min_match = std::numeric_limits<int>::max();
984 bool found;
986 #ifdef LUABIND_NO_ERROR_CHECKING
988 if (rep->overloads.size() == 1)
990 match_index = 0;
992 else
995 #endif
997 int num_params = lua_gettop(L) - 1;
998 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
1000 #ifdef LUABIND_NO_ERROR_CHECKING
1004 #else
1006 if (!found)
1009 std::string msg = "no constructor of '";
1010 msg += base->m_name;
1011 msg += "' matched the arguments (";
1012 msg += stack_content_by_name(L, 2);
1013 msg += ")";
1014 lua_pushstring(L, msg.c_str());
1016 lua_error(L);
1018 else if (ambiguous)
1021 std::string msg = "call of overloaded constructor '";
1022 msg += base->m_name;
1023 msg += "(";
1024 msg += stack_content_by_name(L, 2);
1025 msg += ")' is ambiguous";
1026 lua_pushstring(L, msg.c_str());
1028 lua_error(L);
1031 // TODO: should this be a warning or something?
1033 // since the derived class is a lua class
1034 // it may have reimplemented virtual functions
1035 // therefore, we have to instantiate the Basewrapper
1036 // if there is no basewrapper, throw a run-time error
1037 if (!rep->overloads[match_index].has_wrapped_construct())
1040 std::string msg = "Cannot derive from C++ class '";
1041 msg += base->name();
1042 msg += "'. It does not have a wrapped type";
1043 lua_pushstring(L, msg.c_str());
1045 lua_error(L);
1048 #endif
1050 #ifndef LUABIND_NO_EXCEPTIONS
1055 #endif
1056 lua_pushvalue(L, lua_upvalueindex(2));
1057 weak_ref backref(L, -1);
1058 lua_pop(L, 1);
1060 void* storage_ptr = obj->ptr();
1062 if (!rep->overloads[match_index].has_wrapped_construct())
1064 // if the type doesn't have a wrapped type, use the ordinary constructor
1065 void* instance = rep->overloads[match_index].construct(L, backref);
1067 if (crep->has_holder())
1069 crep->m_construct_holder(storage_ptr, instance);
1071 else
1073 obj->set_object(instance);
1076 else
1078 // get reference to lua object
1079 /* lua_pushvalue(L, lua_upvalueindex(2));
1080 detail::lua_reference ref;
1081 ref.set(L);
1082 void* instance = rep->overloads[match_index].construct_wrapped(L, ref);*/
1084 void* instance = rep->overloads[match_index].construct_wrapped(L, backref);
1086 if (crep->has_holder())
1088 crep->m_construct_holder(storage_ptr, instance);
1090 else
1092 obj->set_object(instance);
1095 // TODO: is the wrapped type destructed correctly?
1096 // it should, since the destructor is either the wrapped type's
1097 // destructor or the base type's destructor, depending on wether
1098 // the type has a wrapped type or not.
1099 obj->set_destructor(base->destructor());
1100 return 0;
1102 #ifndef LUABIND_NO_EXCEPTIONS
1105 catch(const error&)
1108 catch(const std::exception& e)
1110 lua_pushstring(L, e.what());
1112 catch(const char* s)
1114 lua_pushstring(L, s);
1116 catch(...)
1118 std::string msg = base->m_name;
1119 msg += "() threw an exception";
1120 lua_pushstring(L, msg.c_str());
1122 // can only be reached if an exception was thrown
1123 lua_error(L);
1124 #endif
1127 return 0;
1133 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L)
1135 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1137 // get first table
1138 crep->get_table(L);
1140 // copy key, value
1141 lua_pushvalue(L, -3);
1142 lua_pushvalue(L, -3);
1143 lua_rawset(L, -3);
1144 // pop table
1145 lua_pop(L, 1);
1147 // get default table
1148 crep->get_default_table(L);
1149 lua_replace(L, 1);
1150 lua_rawset(L, -3);
1152 crep->m_operator_cache = 0; // invalidate cache
1154 return 0;
1157 int luabind::detail::class_rep::construct_lua_class_callback(lua_State* L)
1159 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1161 int args = lua_gettop(L);
1163 // lua stack: crep <arguments>
1165 lua_newtable(L);
1166 detail::lua_reference ref;
1167 ref.set(L);
1169 bool has_bases = !crep->bases().empty();
1171 if (has_bases)
1173 lua_pushstring(L, "super");
1174 lua_pushvalue(L, 1); // crep
1177 // lua stack: crep <arguments> "super" crep
1178 // or
1179 // lua stack: crep <arguments>
1181 // if we have a baseclass we set the flag to say that the super has not yet been called
1182 // we will use this flag later to check that it actually was called from __init()
1183 int flags = object_rep::lua_class | object_rep::owner | (has_bases ? object_rep::call_super : 0);
1185 // void* obj_ptr = lua_newuserdata(L, sizeof(object_rep));
1186 void* obj_ptr;
1187 void* held_storage;
1189 boost::tie(obj_ptr, held_storage) = crep->allocate(L);
1190 (new(obj_ptr) object_rep(crep, flags, ref))->set_object(held_storage);
1192 detail::getref(L, crep->metatable_ref());
1193 lua_setmetatable(L, -2);
1195 // lua stack: crep <arguments> "super" crep obj_ptr
1196 // or
1197 // lua stack: crep <arguments> obj_ptr
1199 if (has_bases) lua_pushvalue(L, -1); // obj_ptr
1200 lua_replace(L, 1); // obj_ptr
1202 // lua stack: obj_ptr <arguments> "super" crep obj_ptr
1203 // or
1204 // lua stack: obj_ptr <arguments>
1206 if (has_bases)
1208 lua_pushcclosure(L, super_callback, 2);
1209 // lua stack: crep <arguments> "super" function
1210 lua_settable(L, LUA_GLOBALSINDEX);
1213 // lua stack: crep <arguments>
1215 lua_pushvalue(L, 1);
1216 lua_insert(L, 1);
1218 crep->get_table(L);
1219 lua_pushstring(L, "__init");
1220 lua_gettable(L, -2);
1222 #ifndef LUABIND_NO_ERROR_CHECKING
1224 // TODO: should this be a run-time error?
1225 // maybe the default behavior should be to just call
1226 // the base calss' constructor. We should register
1227 // the super callback funktion as __init
1228 if (!lua_isfunction(L, -1))
1231 std::string msg = crep->name();
1232 msg += ":__init is not defined";
1233 lua_pushstring(L, msg.c_str());
1235 lua_error(L);
1238 #endif
1240 lua_insert(L, 2); // function first on stack
1241 lua_pop(L, 1);
1242 // TODO: lua_call may invoke longjump! make sure we don't have any memory leaks!
1243 // we don't have any stack objects here
1244 lua_call(L, args, 0);
1246 #ifndef LUABIND_NO_ERROR_CHECKING
1248 object_rep* obj = static_cast<object_rep*>(obj_ptr);
1249 if (obj->flags() & object_rep::call_super)
1251 lua_pushstring(L, "derived class must call super on base");
1252 lua_error(L);
1255 #endif
1257 return 1;
1260 // called from the metamethod for __index
1261 // obj is the object pointer
1262 int luabind::detail::class_rep::lua_class_gettable(lua_State* L)
1264 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1265 class_rep* crep = obj->crep();
1267 #ifndef LUABIND_NO_ERROR_CHECKING
1269 if (obj->flags() & object_rep::call_super)
1271 lua_pushstring(L, "derived class must call super on base");
1272 lua_error(L);
1275 #endif
1277 // we have to ignore the first argument since this may point to
1278 // a method that is not present in this class (but in a subclass)
1280 // BUG: This might catch members called "__ok\0foobar"
1281 const char* key = lua_tostring(L, 2);
1283 if (key && !std::strcmp(key, "__ok"))
1285 class_rep* crep = obj->crep();
1287 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
1288 : obj->ptr();
1290 lua_pushboolean(L, p != 0);
1291 return 1;
1294 // first look in the instance's table
1295 detail::lua_reference const& tbl = obj->get_lua_table();
1296 assert(tbl.is_valid());
1297 tbl.get(L);
1298 lua_pushvalue(L, 2);
1299 lua_gettable(L, -2);
1300 if (!lua_isnil(L, -1))
1302 lua_remove(L, -2); // remove table
1303 return 1;
1305 lua_pop(L, 2);
1307 // then look in the class' table
1308 crep->get_table(L);
1309 lua_pushvalue(L, 2);
1310 lua_gettable(L, -2);
1312 if (!lua_isnil(L, -1))
1314 lua_remove(L, -2); // more table
1315 return 1;
1318 lua_pop(L, 2);
1320 if (lua_isnil(L, 2))
1322 lua_pushnil(L);
1323 return 1;
1326 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_getters.find(key);
1327 if (j != crep->m_getters.end())
1329 // the name is a data member
1330 return j->second.func(L, j->second.pointer_offset);
1333 lua_pushnil(L);
1334 return 1;
1337 // called from the metamethod for __newindex
1338 // obj is the object pointer
1339 int luabind::detail::class_rep::lua_class_settable(lua_State* L)
1341 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1342 class_rep* crep = obj->crep();
1344 #ifndef LUABIND_NO_ERROR_CHECKING
1346 if (obj->flags() & object_rep::call_super)
1348 // this block makes sure the std::string is destructed
1349 // before lua_error is called
1351 std::string msg = "derived class '";
1352 msg += crep->name();
1353 msg += "'must call super on base";
1354 lua_pushstring(L, msg.c_str());
1356 lua_error(L);
1359 #endif
1361 // we have to ignore the first argument since this may point to
1362 // a method that is not present in this class (but in a subclass)
1363 // BUG: This will not work with keys with extra nulls in them
1364 const char* key = lua_tostring(L, 2);
1367 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_setters.find(key);
1369 // if the strlen(key) is not the true length,
1370 // it means that the member-name contains
1371 // extra nulls. luabind does not support such
1372 // names as member names. So, use the lua
1373 // table as fall-back
1374 if (j == crep->m_setters.end()
1375 || std::strlen(key) != lua_strlen(L, 2))
1377 std::map<const char*, class_rep::callback, ltstr>::iterator k = crep->m_getters.find(key);
1379 #ifndef LUABIND_NO_ERROR_CHECKING
1381 if (k != crep->m_getters.end())
1384 std::string msg = "cannot set property '";
1385 msg += crep->name();
1386 msg += ".";
1387 msg += key;
1388 msg += "', because it's read only";
1389 lua_pushstring(L, msg.c_str());
1391 lua_error(L);
1394 #endif
1396 detail::lua_reference const& tbl = obj->get_lua_table();
1397 assert(tbl.is_valid());
1398 tbl.get(L);
1399 lua_replace(L, 1);
1400 lua_settable(L, 1);
1402 else
1404 // the name is a data member
1405 j->second.func(L, j->second.pointer_offset);
1408 return 0;
1412 stack:
1413 1: class_rep
1414 2: member name
1416 int luabind::detail::class_rep::static_class_gettable(lua_State* L)
1418 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1420 // look in the static function table
1421 crep->get_default_table(L);
1422 lua_pushvalue(L, 2);
1423 lua_gettable(L, -2);
1424 if (!lua_isnil(L, -1)) return 1;
1425 else lua_pop(L, 2);
1427 const char* key = lua_tostring(L, 2);
1429 if (std::strlen(key) != lua_strlen(L, 2))
1431 lua_pushnil(L);
1432 return 1;
1435 std::map<const char*, int, ltstr>::const_iterator j = crep->m_static_constants.find(key);
1437 if (j != crep->m_static_constants.end())
1439 lua_pushnumber(L, j->second);
1440 return 1;
1443 #ifndef LUABIND_NO_ERROR_CHECKING
1446 std::string msg = "no static '";
1447 msg += key;
1448 msg += "' in class '";
1449 msg += crep->name();
1450 msg += "'";
1451 lua_pushstring(L, msg.c_str());
1453 lua_error(L);
1455 #endif
1457 lua_pushnil(L);
1459 return 1;
1462 bool luabind::detail::is_class_rep(lua_State* L, int index)
1464 if (lua_getmetatable(L, index) == 0) return false;
1466 lua_pushstring(L, "__luabind_classrep");
1467 lua_gettable(L, -2);
1468 if (lua_toboolean(L, -1))
1470 lua_pop(L, 2);
1471 return true;
1474 lua_pop(L, 2);
1475 return false;
1478 void luabind::detail::finalize(lua_State* L, class_rep* crep)
1480 if (crep->get_class_type() != class_rep::lua_class) return;
1482 // lua_pushvalue(L, -1); // copy the object ref
1483 crep->get_table(L);
1484 lua_pushstring(L, "__finalize");
1485 lua_gettable(L, -2);
1486 lua_remove(L, -2);
1488 if (lua_isnil(L, -1))
1490 lua_pop(L, 1);
1492 else
1494 lua_pushvalue(L, -2);
1495 lua_call(L, 1, 0);
1498 for (std::vector<class_rep::base_info>::const_iterator
1499 i = crep->bases().begin(); i != crep->bases().end(); ++i)
1501 if (i->base) finalize(L, i->base);
1505 void* luabind::detail::class_rep::convert_to(
1506 LUABIND_TYPE_INFO target_type
1507 , const object_rep* obj
1508 , void* target_memory) const
1510 // TODO: since this is a member function, we don't have to use the accesor functions for
1511 // the types and the extractor
1513 assert(obj == 0 || obj->crep() == this);
1515 int steps = 0;
1516 int offset = 0;
1517 if (!(LUABIND_TYPE_INFO_EQUAL(holder_type(), target_type))
1518 && !(LUABIND_TYPE_INFO_EQUAL(const_holder_type(), target_type)))
1520 steps = implicit_cast(this, target_type, offset);
1523 // should never be called with a type that can't be cast
1524 assert((steps >= 0) && "internal error, please report");
1526 if (LUABIND_TYPE_INFO_EQUAL(target_type, holder_type()))
1528 if (obj == 0)
1530 // we are trying to convert nil to a holder type
1531 m_default_construct_holder(target_memory);
1532 return target_memory;
1534 // if the type we are trying to convert to is the holder_type
1535 // it means that his crep has a holder_type (since it would have
1536 // been invalid otherwise, and T cannot be invalid). It also means
1537 // that we need no conversion, since the holder_type is what the
1538 // object points to.
1539 return obj->ptr();
1542 if (LUABIND_TYPE_INFO_EQUAL(target_type, const_holder_type()))
1544 if (obj == 0)
1546 // we are trying to convert nil to a const holder type
1547 m_default_construct_const_holder(target_memory);
1548 return target_memory;
1551 if (obj->flags() & object_rep::constant)
1553 // we are holding a constant
1554 return obj->ptr();
1556 else
1558 // we are holding a non-constant, we need to convert it
1559 // to a const_holder.
1560 m_const_converter(obj->ptr(), target_memory);
1561 return target_memory;
1565 void* raw_pointer;
1567 if (has_holder())
1569 assert(obj);
1570 // this means that we have a holder type where the
1571 // raw-pointer needs to be extracted
1572 raw_pointer = extractor()(obj->ptr());
1574 else
1576 if (obj == 0) raw_pointer = 0;
1577 else raw_pointer = obj->ptr();
1580 return static_cast<char*>(raw_pointer) + offset;
1583 void luabind::detail::class_rep::cache_operators(lua_State* L)
1585 m_operator_cache = 0x1;
1587 for (int i = 0; i < number_of_operators; ++i)
1589 get_table(L);
1590 lua_pushstring(L, get_operator_name(i));
1591 lua_rawget(L, -2);
1593 if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1);
1595 lua_pop(L, 2);
1599 bool luabind::detail::class_rep::has_operator_in_lua(lua_State* L, int id)
1601 if ((m_operator_cache & 0x1) == 0)
1602 cache_operators(L);
1604 const int mask = 1 << (id + 1);
1606 return (m_operator_cache & mask) != 0;
1610 // this will merge all overloads of fun into the list of
1611 // overloads in this class
1612 void luabind::detail::class_rep::add_method(luabind::detail::method_rep const& fun)
1614 typedef std::list<detail::method_rep> methods_t;
1616 methods_t::iterator m = std::find_if(
1617 m_methods.begin()
1618 , m_methods.end()
1619 , method_name(fun.name));
1620 if (m == m_methods.end())
1622 m_methods.push_back(method_rep());
1623 m = m_methods.end();
1624 std::advance(m, -1);
1625 m->name = fun.name;
1627 m->crep = this;
1629 typedef std::vector<detail::overload_rep> overloads_t;
1631 for (overloads_t::const_iterator j = fun.overloads().begin();
1632 j != fun.overloads().end(); ++j)
1634 detail::overload_rep o = *j;
1635 m->add_overload(o);
1639 // this function will add all the overloads in method rep to
1640 // this class' lua tables. If there already are overloads with this
1641 // name, thses will simply be appended to the overload list
1642 void luabind::detail::class_rep::register_methods(lua_State* L)
1644 LUABIND_CHECK_STACK(L);
1645 // insert the function in the normal member table
1646 // and in the default member table
1647 m_default_table.push(L);
1648 m_table.push(L);
1650 // pops the tables
1651 detail::stack_pop pop_tables(L, 2);
1653 for (std::list<method_rep>::const_iterator m = m_methods.begin();
1654 m != m_methods.end(); ++m)
1656 // create the function closure in m_table
1657 lua_pushstring(L, m->name);
1658 lua_pushlightuserdata(L, const_cast<void*>((const void*)&(*m)));
1659 lua_pushboolean(L, 0);
1660 lua_pushlightuserdata(L, reinterpret_cast<void*>(0x1337));
1661 lua_pushcclosure(L, function_dispatcher, 3);
1662 lua_settable(L, -3);
1664 // create the function closure in m_default_table
1665 lua_pushstring(L, m->name);
1666 lua_pushlightuserdata(L, const_cast<void*>((const void*)&(*m)));
1667 lua_pushboolean(L, 1);
1668 lua_pushlightuserdata(L, reinterpret_cast<void*>(0x1337));
1669 lua_pushcclosure(L, function_dispatcher, 3);
1670 lua_settable(L, -4);
1674 const class_rep::property_map& luabind::detail::class_rep::properties() const
1676 return m_getters;