removed some warnings and fixed a bug in the copy constructor of functor.
[luabind.git] / src / class_rep.cpp
blob246b9b87a32720168ee275e0f0c22c7e10a14cf1
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 #define LUABIND_BUILDING
27 #include <luabind/luabind.hpp>
28 #include <utility>
30 using namespace luabind::detail;
33 #ifndef LUABIND_NO_ERROR_CHECKING
35 std::string luabind::detail::get_overload_signatures_candidates(lua_State* L, std::vector<const overload_rep_base*>::iterator start, std::vector<const overload_rep_base*>::iterator end, std::string name)
37 std::string s;
38 for (; start != end; ++start)
40 s += name;
41 (*start)->get_signature(L, s);
42 s += "\n";
44 return s;
47 #endif
50 luabind::detail::class_rep::class_rep(LUABIND_TYPE_INFO type
51 , const char* name
52 , lua_State* L
53 , void(*destructor)(void*)
54 , void(*const_holder_destructor)(void*)
55 , LUABIND_TYPE_INFO holder_type
56 , LUABIND_TYPE_INFO const_holder_type
57 , void*(*extractor)(void*)
58 , const void*(*const_extractor)(void*)
59 , void(*const_converter)(void*,void*)
60 , void(*construct_holder)(void*,void*)
61 , void(*construct_const_holder)(void*,void*)
62 , int holder_size
63 , int holder_alignment)
65 : m_type(type)
66 , m_holder_type(holder_type)
67 , m_const_holder_type(const_holder_type)
68 , m_extractor(extractor)
69 , m_const_extractor(const_extractor)
70 , m_const_converter(const_converter)
71 , m_construct_holder(construct_holder)
72 , m_construct_const_holder(construct_const_holder)
73 , m_holder_size(holder_size)
74 , m_holder_alignment(holder_alignment)
75 , m_name(name)
76 , m_table_ref(LUA_NOREF)
77 , m_class_type(cpp_class)
78 , m_destructor(destructor)
79 , m_const_holder_destructor(const_holder_destructor)
80 , m_operator_cache(0)
82 assert(m_holder_alignment >= 1 && "internal error");
84 lua_newtable(L);
85 m_table_ref = detail::ref(L);
87 class_registry* r = class_registry::get_registry(L);
88 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
90 detail::getref(L, r->cpp_class());
91 lua_setmetatable(L, -2);
93 lua_pushvalue(L, -1); // duplicate our user data
94 m_self_ref = detail::ref(L); // pop one of them
96 m_instance_metatable = r->cpp_instance();
99 luabind::detail::class_rep::class_rep(lua_State* L, const char* name)
100 : m_type(LUABIND_INVALID_TYPE_INFO)
101 , m_holder_type(LUABIND_INVALID_TYPE_INFO)
102 , m_const_holder_type(LUABIND_INVALID_TYPE_INFO)
103 , m_extractor(0)
104 , m_const_extractor(0)
105 , m_const_converter(0)
106 , m_construct_holder(0)
107 , m_construct_const_holder(0)
108 , m_holder_size(0)
109 , m_holder_alignment(1)
110 , m_class_type(lua_class)
111 , m_destructor(0)
112 , m_const_holder_destructor(0)
113 , m_operator_cache(0)
115 #ifndef LUABIND_DONT_COPY_STRINGS
116 m_strings.push_back(detail::dup_string(name));
117 m_name = m_strings.back();
118 #else
119 m_name = name;
120 #endif
121 lua_newtable(L);
122 m_table_ref = detail::ref(L);
124 class_registry* r = class_registry::get_registry(L);
125 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
127 detail::getref(L, r->lua_class());
128 lua_setmetatable(L, -2);
129 lua_pushvalue(L, -1); // duplicate our user data
130 m_self_ref = detail::ref(L); // pop one of them
132 m_instance_metatable = r->lua_instance();
135 luabind::detail::class_rep::~class_rep()
137 #ifndef LUABIND_DONT_COPY_STRINGS
138 for (std::vector<char*>::iterator i = m_strings.begin();
139 i != m_strings.end(); ++i)
141 delete[] *i;
143 #endif
146 std::pair<void*,void*>
147 luabind::detail::class_rep::allocate(lua_State* L) const
149 const int overlap = sizeof(object_rep)&(m_holder_alignment-1);
150 const int padding = overlap==0?0:m_holder_alignment-overlap;
151 const int size = sizeof(object_rep) + padding + m_holder_size;
153 char* mem = static_cast<char*>(lua_newuserdata(L, size));
154 char* ptr = mem + sizeof(object_rep) + padding;
156 return std::pair<void*,void*>(mem,ptr);
159 //#include <iostream>
161 int luabind::detail::class_rep::gettable(lua_State* L)
163 if (lua_isnil(L, 2))
165 lua_pushnil(L);
166 return 1;
169 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
171 // we have to ignore the first argument since this may point to
172 // a method that is not present in this class (but in a subclass)
173 const char* key = lua_tostring(L, 2);
175 if (key && !strcmp(key, "__ok"))
177 class_rep* crep = obj->crep();
179 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
180 : obj->ptr();
182 lua_pushboolean(L, p != 0);
183 return 1;
186 detail::getref(L, obj->crep()->table_ref());
187 lua_pushvalue(L, 2);
188 lua_gettable(L, -2);
190 if (!lua_isnil(L, -1))
192 // std::cout << "method found in lua table: " << key << "\n";
193 lua_remove(L, -2); // more table
194 return 1;
197 lua_pop(L, 2);
199 std::map<const char*, method_rep, ltstr>::iterator i = m_methods.find(key);
201 if (i != m_methods.end())
203 // the name is a method, return it
204 lua_pushlightuserdata(L, &i->second);
205 lua_pushcclosure(L, function_dispatcher, 1);
206 return 1;
209 std::map<const char*, callback, ltstr>::iterator j = m_getters.find(key);
210 if (j != m_getters.end())
212 // the name is a data member
213 return j->second.func(L, j->second.pointer_offset);
216 lua_pushnil(L);
217 return 1;
220 // called from the metamethod for __newindex
221 // the object pointer is passed on the lua stack
222 bool luabind::detail::class_rep::settable(lua_State* L)
224 if (lua_isnil(L, 2))
226 return false;
229 // we have to ignore the first argument since this may point to
230 // a method that is not present in this class (but in a subclass)
231 const char* key = lua_tostring(L, 2);
232 std::map<const char*, callback, ltstr>::iterator j = m_setters.find(key);
233 if (j != m_setters.end())
235 // the name is a data member
236 j->second.func(L, j->second.pointer_offset);
237 return true;
240 return false; // false means that we don't have a member with the given name
243 int class_rep::gettable_dispatcher(lua_State* L)
245 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
246 return obj->crep()->gettable(L);
249 // this is called as __newindex metamethod on every instance of this class
250 int luabind::detail::class_rep::settable_dispatcher(lua_State* L)
252 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
254 bool success = obj->crep()->settable(L);
256 #ifndef LUABIND_NO_ERROR_CHECKING
258 if (!success)
260 // this block is needed to make sure the std::string is destructed before
261 // lua_error() is called
262 #ifdef BOOST_MSVC
264 // msvc has a bug which deletes the string twice, that's
265 // why we have to create it on the heap
266 std::string* msg = new std::string("cannot set attribute '");
267 *msg += obj->crep()->m_name;
268 *msg += ".";
269 *msg += lua_tostring(L, -2);
270 *msg += "'";
271 lua_pushstring(L, msg->c_str());
272 delete msg;
274 #else
276 std::string msg = "cannot set attribute '";
277 msg += obj->crep()->m_name;
278 msg += ".";
279 msg += lua_tostring(L, -2);
280 msg += "'";
281 lua_pushstring(L, msg.c_str());
283 #endif
284 lua_error(L);
287 #endif
289 return 0;
293 int luabind::detail::class_rep::operator_dispatcher(lua_State* L)
295 int id = static_cast<int>(lua_tonumber(L, lua_upvalueindex(1)));
297 int operand_id = 0;
299 object_rep* operand[2];
300 for (int i = 0; i < 2; ++i)
301 operand[i] = detail::is_class_object(L, i + 1);
303 // we cannot compare the types here, we have to compare the pointers of the class_reps
304 // since all lua-classes have the same type (LUABIND_INVALID_TYPE_INFO)
305 if (operand[0] && operand[1])
306 if (operand[0]->crep() == operand[1]->crep()) operand[1] = 0;
308 std::vector<operator_callback>* overloads[2];
309 for (int i = 0; i < 2; ++i)
310 if (operand[i]) overloads[i] = &operand[i]->crep()->m_operators[id]; else overloads[i] = 0;
312 std::size_t num_overloads[2];
313 for (int i = 0; i < 2; ++i)
314 if (overloads[i]) num_overloads[i] = overloads[i]->size(); else num_overloads[i] = 0;
316 for (int i = 0; i < 2; ++i)
317 if (operand[i] && operand[i]->crep()->get_class_type() == class_rep::lua_class)
319 /* // if this is a lua class we have to
320 // look in its table to see if there's
321 // any overload of this operator
322 detail::getref(L, operand[i]->crep()->table_ref());
323 lua_pushstring(L, get_operator_name(id));
324 lua_rawget(L, -2);
325 // if we have tha operator, set num_overloads to 1
326 if (lua_isfunction(L, -1)) num_overloads[i] = 1;
327 lua_pop(L, 2);*/
329 if (operand[i]->crep()->has_operator_in_lua(L, id))
330 num_overloads[i] = 1;
333 bool ambiguous = false;
334 int match_index = -1;
335 int min_match = std::numeric_limits<int>::max();
337 #ifdef LUABIND_NO_ERROR_CHECKING
339 if (num_overloads[0] == 1 && num_overloads[1] == 0)
341 operand_id = 0;
342 match_index = 0;
344 else if (num_overloads[0] == 0 && num_overloads[1] == 1)
346 operand_id = 1;
347 match_index = 0;
349 else
352 #endif
354 int num_params = lua_gettop(L);
356 // have look at the right operand.
357 // if the right operand is a class and
358 // not the same class as this, we have to
359 // try to match it's operators too
360 for (int i = 0; i < 2; ++i)
362 if (num_overloads[i])
364 if (operand[i]->crep()->get_class_type() == class_rep::lua_class)
366 // if this is a lua class
367 // and num_overloads is > 0
368 // it means that it has implemented
369 // this operator. Set match_index to
370 // 0 to signal that this operand has
371 // an overload, but leave the min_match
372 // at int-max to mark it as a last fallback
373 operand_id = i;
374 if (match_index == -1) match_index = 0;
376 else if (find_best_match(
378 , &overloads[i]->front()
379 , overloads[i]->size()
380 , sizeof(operator_callback)
381 , ambiguous
382 , min_match
383 , match_index
384 , num_params))
386 operand_id = i;
392 #ifdef LUABIND_NO_ERROR_CHECKING
396 #else
398 if (match_index == -1)
400 // this block is needed to make sure the std::string is destructed before
401 // lua_error() is called
403 std::string msg = "no operator ";
404 msg += get_operator_symbol(id);
405 msg += " matched the arguments (";
406 msg += stack_content_by_name(L, 1);
407 msg += ")\ncandidates are:\n";
409 for (int i = 0; i < 2; ++i)
411 if (overloads[i])
413 msg += get_overload_signatures(
415 , overloads[i]->begin()
416 , overloads[i]->end()
417 , get_operator_symbol(id));
419 else
421 // if num_overloads is > 0 it would mean that this is
422 // a lua class with this operator overloaded. And if
423 // that's the case, it should always match (and if an
424 // operator matches, we never come here).
425 assert(num_overloads[i] == 0 && "internal error");
429 lua_pushstring(L, msg.c_str());
431 lua_error(L);
433 else if (ambiguous)
435 // this block is needed to make sure the std::string is destructed before
436 // lua_error() is called
438 std::string msg = "call of overloaded operator ";
439 msg += get_operator_symbol(id);
440 msg += " (";
441 msg += stack_content_by_name(L, 1);
442 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
444 std::vector<const overload_rep_base*> candidates;
445 if (overloads[0])
446 find_exact_match(L, &overloads[0]->front(), overloads[0]->size(), sizeof(operator_callback), min_match, num_params, candidates);
448 if (overloads[1])
449 find_exact_match(L, &overloads[1]->front(), overloads[1]->size(), sizeof(operator_callback), min_match, num_params, candidates);
451 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), get_operator_symbol(id));
453 lua_pushstring(L, msg.c_str());
455 lua_error(L);
458 #endif
460 if (operand[operand_id]->crep()->get_class_type() == class_rep::lua_class)
462 detail::getref(L, operand[operand_id]->crep()->table_ref());
463 lua_pushstring(L, get_operator_name(id));
464 lua_rawget(L, -2);
465 lua_insert(L, -4); // move the function to the bottom
466 lua_pop(L, 1); // remove the table
467 lua_call(L, 2, 1);
468 return 1;
470 else
472 return (*overloads[operand_id])[match_index].call(L);
476 // this is called as metamethod __call on the class_rep.
477 int luabind::detail::class_rep::constructor_dispatcher(lua_State* L)
479 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
480 construct_rep* rep = &crep->m_constructor;
482 bool ambiguous = false;
483 int match_index = -1;
484 int min_match = std::numeric_limits<int>::max();
485 bool found;
487 #ifdef LUABIND_NO_ERROR_CHECKING
489 if (rep->overloads.size() == 1)
491 match_index = 0;
493 else
496 #endif
498 int num_params = lua_gettop(L) - 1;
499 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
501 #ifdef LUABIND_NO_ERROR_CHECKING
504 #else
506 if (!found)
508 // this block is needed to make sure the std::string is destructed before
509 // lua_error() is called
511 std::string msg = "no constructor of '";
512 msg += crep->name();
513 msg += "' matched the arguments (";
514 msg += stack_content_by_name(L, 2);
515 msg += ")\n candidates are:\n";
517 msg += get_overload_signatures(L, rep->overloads.begin(), rep->overloads.end(), crep->name());
519 lua_pushstring(L, msg.c_str());
521 lua_error(L);
523 else if (ambiguous)
525 // this block is needed to make sure the std::string is destructed before
526 // lua_error() is called
528 std::string msg = "call of overloaded constructor '";
529 msg += crep->m_name;
530 msg += "(";
531 msg += stack_content_by_name(L, 2);
532 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
534 std::vector<const overload_rep_base*> candidates;
535 find_exact_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), min_match, num_params, candidates);
536 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), crep->name());
538 lua_pushstring(L, msg.c_str());
540 lua_error(L);
543 #endif
545 #ifndef LUABIND_NO_EXCEPTIONS
550 #endif
552 void* object_ptr = rep->overloads[match_index].construct(L);
554 void* obj_rep;
555 void* held;
557 boost::tie(obj_rep,held) = crep->allocate(L);
559 if (crep->has_holder())
561 crep->m_construct_holder(held, object_ptr);
562 object_ptr = held;
564 new(obj_rep) object_rep(object_ptr, crep, object_rep::owner, crep->destructor());
566 detail::getref(L, crep->m_instance_metatable);
567 lua_setmetatable(L, -2);
568 return 1;
570 #ifndef LUABIND_NO_EXCEPTIONS
574 catch(const std::exception& e)
576 lua_pushstring(L, e.what());
578 catch(const char* s)
580 lua_pushstring(L, s);
582 catch(...)
585 std::string msg = crep->name();
586 msg += "() threw an exception";
587 lua_pushstring(L, msg.c_str());
591 // we can only reach this line if an exception was thrown
592 lua_error(L);
593 return 0; // will never be reached
595 #endif
599 // the functions dispatcher assumes the following:
600 // there is one upvalue that points to the method_rep that this dispatcher is to call
601 // the first parameter on the lua stack is an object_rep that points to the object the
602 // call is being made on
603 int luabind::detail::class_rep::function_dispatcher(lua_State* L)
605 method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
606 object_rep* obj = reinterpret_cast<object_rep*>(lua_touserdata(L, 1));
608 #ifndef LUABIND_NO_ERROR_CHECKING
610 if (is_class_object(L, 1) == 0)
613 std::string msg = "No self reference given as first parameter to member function '";
614 msg += rep->crep->name();
615 msg += ":";
616 msg += rep->name;
617 msg += "'. Have you used '.' instead of ':'?";
619 lua_pushstring(L, msg.c_str());
621 lua_error(L);
624 int p;
625 if (implicit_cast(obj->crep(), rep->crep->type(), p) < 0)
628 std::string msg = "invalid self reference given to '";
629 msg += rep->crep->name();
630 msg += ":";
631 msg += rep->name;
632 msg += "'";
633 lua_pushstring(L, msg.c_str());
635 lua_error(L);
638 #endif
640 bool ambiguous = false;
641 int match_index = -1;
642 int min_match = std::numeric_limits<int>::max();
643 bool found;
645 #ifdef LUABIND_NO_ERROR_CHECKING
646 if (rep->overloads().size() == 1)
648 match_index = 0;
650 else
652 #endif
654 int num_params = lua_gettop(L) - 1;
655 found = find_best_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), ambiguous, min_match, match_index, num_params);
657 #ifdef LUABIND_NO_ERROR_CHECKING
661 #else
663 if (!found)
666 std::string msg = "no overload of '";
667 msg += rep->crep->name();
668 msg += ":";
669 msg += rep->name;
670 msg += "' matched the arguments (";
671 msg += stack_content_by_name(L, 2);
672 msg += ")\ncandidates are:\n";
674 std::string function_name;
675 function_name += rep->crep->name();
676 function_name += ":";
677 function_name += rep->name;
679 msg += get_overload_signatures(L, rep->overloads().begin(), rep->overloads().end(), function_name);
681 lua_pushstring(L, msg.c_str());
683 lua_error(L);
685 else if (ambiguous)
688 std::string msg = "call of overloaded '";
689 msg += rep->crep->name();
690 msg += ":";
691 msg += rep->name;
692 msg += "(";
693 msg += stack_content_by_name(L, 2);
694 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
696 std::vector<const overload_rep_base*> candidates;
697 find_exact_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), min_match, num_params, candidates);
699 std::string function_name;
700 function_name += rep->crep->name();
701 function_name += ":";
702 function_name += rep->name;
704 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), function_name);
706 lua_pushstring(L, msg.c_str());
708 lua_error(L);
711 #endif
713 #ifndef LUABIND_NO_EXCEPTIONS
718 #endif
720 const overload_rep& o = rep->overloads()[match_index];
721 return o.call(L, *obj);
723 #ifndef LUABIND_NO_EXCEPTIONS
726 catch(const std::exception& e)
728 lua_pushstring(L, e.what());
730 catch (const char* s)
732 lua_pushstring(L, s);
734 catch(...)
736 std::string msg = rep->crep->name();
737 msg += ":";
738 msg += rep->name;
739 msg += "() threw an exception";
740 lua_pushstring(L, msg.c_str());
742 // we can only reach this line if an exception was thrown
743 lua_error(L);
744 return 0; // will never be reached
746 #endif
750 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo)
752 // If you hit this assert you are deriving from a type that is not registered
753 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
754 // Please note that if you don't need to have access to the base class or the
755 // conversion from the derived class to the base class, you don't need
756 // to tell luabind that it derives.
757 assert(binfo.base && "You cannot derive from an unregistered type");
759 class_rep* bcrep = binfo.base;
761 // import all functions from the base
762 for (std::map<const char*, method_rep, ltstr>::const_iterator i = bcrep->m_methods.begin();
763 i != bcrep->m_methods.end(); ++i)
765 // If we would assume that our base class will not be garbage collected until
766 // this class is collected, we wouldn't had to copy these strings.
767 #ifndef LUABIND_DONT_COPY_STRINGS
768 m_strings.push_back(dup_string(i->first));
769 method_rep& m = m_methods[m_strings.back()];
770 #else
771 method_rep& m = m_methods[i->first];
772 #endif
773 m.name = i->first;
774 m.crep = this;
776 for (std::vector<overload_rep>::const_iterator j = i->second.overloads().begin();
777 j != i->second.overloads().end(); ++j)
779 overload_rep o = *j;
780 o.add_offset(binfo.pointer_offset);
781 m.add_overload(o);
785 // import all getters from the base
786 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_getters.begin();
787 i != bcrep->m_getters.end(); ++i)
789 #ifndef LUABIND_DONT_COPY_STRINGS
790 m_strings.push_back(dup_string(i->first));
791 callback& m = m_getters[m_strings.back()];
792 #else
793 callback& m = m_getters[i->first];
794 #endif
795 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
796 m.func = i->second.func;
799 // import all setters from the base
800 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_setters.begin();
801 i != bcrep->m_setters.end(); ++i)
803 #ifndef LUABIND_DONT_COPY_STRINGS
804 // TODO: optimize this by not copying the string if it already exists in m_setters.
805 // This goes for m_getters, m_static_constants and m_functions too. Both here
806 // in add_base() and in the add_function(), add_getter() ... functions.
807 m_strings.push_back(dup_string(i->first));
808 callback& m = m_setters[m_strings.back()];
809 #else
810 callback& m = m_setters[i->first];
811 #endif
812 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
813 m.func = i->second.func;
816 // import all static constants
817 for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin();
818 i != bcrep->m_static_constants.end(); ++i)
820 #ifndef LUABIND_DONT_COPY_STRINGS
821 m_strings.push_back(dup_string(i->first));
822 int& v = m_static_constants[m_strings.back()];
823 #else
824 int& v = m_static_constants[i->first];
825 #endif
826 v = i->second;
829 // import all operators
830 for (int i = 0; i < number_of_operators; ++i)
832 for (std::vector<operator_callback>::const_iterator j = bcrep->m_operators[i].begin();
833 j != bcrep->m_operators[i].end(); ++j)
834 m_operators[i].push_back(*j);
837 // also, save the baseclass info to be used for typecasts
838 m_bases.push_back(binfo);
841 void luabind::detail::class_rep::add_function(const char* name, const overload_rep& o)
844 #ifdef LUABIND_DONT_COPY_STRINGS
845 detail::method_rep& method = m_methods[name];
846 method.name = name;
847 #else
848 m_strings.push_back(dup_string(name));
849 detail::method_rep& method = m_methods[m_strings.back()];
850 method.name = m_strings.back();
851 #endif
853 method.add_overload(o);
854 method.crep = this;
857 void luabind::detail::class_rep::add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
859 callback c;
860 c.func = g;
861 c.pointer_offset = 0;
862 #ifndef LUABIND_DONT_COPY_STRINGS
863 m_strings.push_back(dup_string(name));
864 m_getters[m_strings.back()] = c;
865 #else
866 m_getters[name] = c;
867 #endif
870 void luabind::detail::class_rep::add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
872 callback c;
873 c.func = s;
874 c.pointer_offset = 0;
875 #ifndef LUABIND_DONT_COPY_STRINGS
876 m_strings.push_back(dup_string(name));
877 m_setters[m_strings.back()] = c;
878 #else
879 m_setters[name] = c;
880 #endif
883 #ifndef LUABIND_NO_ERROR_CHECKING
884 void luabind::detail::class_rep::add_operator(lua_State*, int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), void(*sig)(lua_State*, std::string&), int arity)
885 #else
886 void luabind::detail::class_rep::add_operator(lua_State*, int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
887 #endif
889 operator_callback o;
890 o.set_fun(func);
891 o.set_match_fun(matcher);
892 o.set_arity(arity);
894 #ifndef LUABIND_NO_ERROR_CHECKING
896 o.set_sig_fun(sig);
898 #endif
899 m_operators[op_id].push_back(o);
902 void luabind::detail::class_rep::add_static_constant(const char* name, int val)
904 #ifndef LUABIND_DONT_COPY_STRINGS
905 m_strings.push_back(dup_string(name));
906 m_static_constants[m_strings.back()] = val;
907 #else
908 m_static_constants[name] = val;
909 #endif
912 int luabind::detail::class_rep::super_callback(lua_State* L)
914 int args = lua_gettop(L);
916 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, lua_upvalueindex(2)));
917 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
918 class_rep* base = crep->bases()[0].base;
920 if (base->get_class_type() == class_rep::lua_class)
922 if (base->bases().empty())
924 obj->set_flags(obj->flags() & ~object_rep::call_super);
926 lua_pushstring(L, "super");
927 lua_pushnil(L);
928 lua_settable(L, LUA_GLOBALSINDEX);
930 else
932 lua_pushstring(L, "super");
933 lua_pushlightuserdata(L, base);
934 lua_pushvalue(L, lua_upvalueindex(2));
935 lua_pushcclosure(L, super_callback, 2);
936 lua_settable(L, LUA_GLOBALSINDEX);
939 detail::getref(L, base->table_ref());
940 lua_pushstring(L, "__init");
941 lua_gettable(L, -2);
942 lua_insert(L, 1);
943 lua_pop(L, 1);
945 lua_pushvalue(L, lua_upvalueindex(2));
946 lua_insert(L, 2);
948 lua_call(L, args + 1, 0);
950 // TODO: instead of clearing the global variable "super"
951 // store it temporarily in the registry. maybe we should
952 // have some kind of warning if the super global is used?
953 lua_pushstring(L, "super");
954 lua_pushnil(L);
955 lua_settable(L, LUA_GLOBALSINDEX);
957 else
959 obj->set_flags(obj->flags() & ~object_rep::call_super);
961 // we need to push some garbage at index 1 to make the construction work
962 lua_pushboolean(L, 1);
963 lua_insert(L, 1);
965 construct_rep* rep = &base->m_constructor;
967 bool ambiguous = false;
968 int match_index = -1;
969 int min_match = std::numeric_limits<int>::max();
970 bool found;
972 #ifdef LUABIND_NO_ERROR_CHECKING
974 if (rep->overloads.size() == 1)
976 match_index = 0;
978 else
981 #endif
983 int num_params = lua_gettop(L) - 1;
984 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
986 #ifdef LUABIND_NO_ERROR_CHECKING
990 #else
992 if (!found)
995 std::string msg = "no constructor of '";
996 msg += base->m_name;
997 msg += "' matched the arguments (";
998 msg += stack_content_by_name(L, 2);
999 msg += ")";
1000 lua_pushstring(L, msg.c_str());
1002 lua_error(L);
1004 else if (ambiguous)
1007 std::string msg = "call of overloaded constructor '";
1008 msg += base->m_name;
1009 msg += "(";
1010 msg += stack_content_by_name(L, 2);
1011 msg += ")' is ambiguous";
1012 lua_pushstring(L, msg.c_str());
1014 lua_error(L);
1017 // TODO: should this be a warning or something?
1019 // since the derived class is a lua class
1020 // it may have reimplemented virtual functions
1021 // therefore, we have to instantiate the Basewrapper
1022 // if there is no basewrapper, throw a run-time error
1023 if (!rep->overloads[match_index].has_wrapped_construct())
1026 std::string msg = "Cannot derive from C++ class '";
1027 msg += base->name();
1028 msg += "'. It does not have a wrapped type";
1029 lua_pushstring(L, msg.c_str());
1031 lua_error(L);
1034 #endif
1036 #ifndef LUABIND_NO_EXCEPTIONS
1041 #endif
1043 if (!rep->overloads[match_index].has_wrapped_construct())
1045 // if the type doesn't have a wrapped type, use the ordinary constructor
1046 obj->set_object(rep->overloads[match_index].construct(L));
1048 else
1050 // get reference to lua object
1051 lua_pushvalue(L, lua_upvalueindex(2));
1052 int ref = detail::ref(L);
1053 obj->set_object(rep->overloads[match_index].construct_wrapped(L, ref));
1055 // TODO: is the wrapped type destructed correctly?
1056 // it should, since the destructor is either the wrapped type's
1057 // destructor or the base type's destructor, depending on wether
1058 // the type has a wrapped type or not.
1059 obj->set_destructor(base->destructor());
1060 return 0;
1062 #ifndef LUABIND_NO_EXCEPTIONS
1065 catch(const std::exception& e)
1067 lua_pushstring(L, e.what());
1069 catch(const char* s)
1071 lua_pushstring(L, s);
1073 catch(...)
1075 std::string msg = base->m_name;
1076 msg += "() threw an exception";
1077 lua_pushstring(L, msg.c_str());
1079 // can only be reached if an exception was thrown
1080 lua_error(L);
1081 #endif
1084 return 0;
1090 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L)
1092 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1093 detail::getref(L, crep->m_table_ref);
1094 lua_replace(L, 1);
1095 lua_rawset(L, -3);
1097 crep->m_operator_cache = 0; // invalidate cache
1099 return 0;
1102 int luabind::detail::class_rep::construct_lua_class_callback(lua_State* L)
1104 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1106 int args = lua_gettop(L);
1108 // lua stack: crep <arguments>
1110 lua_newtable(L);
1111 int ref = detail::ref(L);
1113 bool has_bases = !crep->bases().empty();
1115 if (has_bases)
1117 lua_pushstring(L, "super");
1118 lua_pushvalue(L, 1); // crep
1121 // lua stack: crep <arguments> "super" crep
1122 // or
1123 // lua stack: crep <arguments>
1125 // if we have a baseclass we set the flag to say that the super has not yet been called
1126 // we will use this flag later to check that it actually was called from __init()
1127 int flags = object_rep::lua_class | object_rep::owner | (has_bases ? object_rep::call_super : 0);
1129 void* obj_ptr = lua_newuserdata(L, sizeof(object_rep));
1130 new(obj_ptr) object_rep(crep, flags, ref);
1132 detail::getref(L, crep->metatable_ref());
1133 lua_setmetatable(L, -2);
1135 // lua stack: crep <arguments> "super" crep obj_ptr
1136 // or
1137 // lua stack: crep <arguments> obj_ptr
1139 if (has_bases) lua_pushvalue(L, -1); // obj_ptr
1140 lua_replace(L, 1); // obj_ptr
1142 // lua stack: obj_ptr <arguments> "super" crep obj_ptr
1143 // or
1144 // lua stack: obj_ptr <arguments>
1146 if (has_bases)
1148 lua_pushcclosure(L, super_callback, 2);
1149 // lua stack: crep <arguments> "super" function
1150 lua_settable(L, LUA_GLOBALSINDEX);
1153 // lua stack: crep <arguments>
1155 lua_pushvalue(L, 1);
1156 lua_insert(L, 1);
1158 detail::getref(L, crep->table_ref());
1159 lua_pushstring(L, "__init");
1160 lua_gettable(L, -2);
1162 #ifndef LUABIND_NO_ERROR_CHECKING
1164 // TODO: should this be a run-time error?
1165 // maybe the default behavior should be to just call
1166 // the base calss' constructor. We should register
1167 // the super callback funktion as __init
1168 if (!lua_isfunction(L, -1))
1171 std::string msg = crep->name();
1172 msg += ":__init is not defined";
1173 lua_pushstring(L, msg.c_str());
1175 lua_error(L);
1178 #endif
1180 lua_insert(L, 2); // function first on stack
1181 lua_pop(L, 1);
1182 // TODO: lua_call may invoke longjump! make sure we don't have any memory leaks!
1183 // we don't have any stack objects here
1184 lua_call(L, args, 0);
1186 #ifndef LUABIND_NO_ERROR_CHECKING
1188 object_rep* obj = static_cast<object_rep*>(obj_ptr);
1189 if (obj->flags() & object_rep::call_super)
1191 lua_pushstring(L, "derived class must call super on base");
1192 lua_error(L);
1195 #endif
1197 return 1;
1200 // called from the metamethod for __index
1201 // obj is the object pointer
1202 int luabind::detail::class_rep::lua_class_gettable(lua_State* L)
1204 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1205 class_rep* crep = obj->crep();
1207 #ifndef LUABIND_NO_ERROR_CHECKING
1209 if (obj->flags() & object_rep::call_super)
1211 lua_pushstring(L, "derived class must call super on base");
1212 lua_error(L);
1215 #endif
1217 // we have to ignore the first argument since this may point to
1218 // a method that is not present in this class (but in a subclass)
1219 const char* key = lua_tostring(L, 2);
1221 if (key && !strcmp(key, "__ok"))
1223 class_rep* crep = obj->crep();
1225 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
1226 : obj->ptr();
1228 lua_pushboolean(L, p != 0);
1229 return 1;
1232 detail::getref(L, obj->lua_table_ref());
1233 lua_pushvalue(L, 2);
1234 lua_gettable(L, -2);
1236 if (!lua_isnil(L, -1))
1238 lua_remove(L, -2); // remove table
1239 return 1;
1242 lua_pop(L, 2);
1244 detail::getref(L, crep->table_ref());
1245 lua_pushvalue(L, 2);
1246 lua_gettable(L, -2);
1248 if (!lua_isnil(L, -1))
1250 lua_remove(L, -2); // more table
1251 return 1;
1254 lua_pop(L, 2);
1256 if (lua_isnil(L, 2))
1258 lua_pushnil(L);
1259 return 1;
1262 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1263 if (i != crep->m_methods.end())
1265 // the name is a method, return it
1266 lua_pushlightuserdata(L, &i->second);
1267 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1268 return 1;
1271 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_getters.find(key);
1272 if (j != crep->m_getters.end())
1274 // the name is a data member
1275 return j->second.func(L, j->second.pointer_offset);
1278 lua_pushnil(L);
1279 return 1;
1282 // called from the metamethod for __newindex
1283 // obj is the object pointer
1284 int luabind::detail::class_rep::lua_class_settable(lua_State* L)
1286 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1287 class_rep* crep = obj->crep();
1289 #ifndef LUABIND_NO_ERROR_CHECKING
1291 if (obj->flags() & object_rep::call_super)
1293 // this block makes sure the std::string is destructed
1294 // before lua_error is called
1296 std::string msg = "derived class '";
1297 msg += crep->name();
1298 msg += "'must call super on base";
1299 lua_pushstring(L, msg.c_str());
1301 lua_error(L);
1304 #endif
1306 // we have to ignore the first argument since this may point to
1307 // a method that is not present in this class (but in a subclass)
1308 const char* key = lua_tostring(L, 2);
1309 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_setters.find(key);
1311 if (j == crep->m_setters.end())
1313 std::map<const char*, class_rep::callback, ltstr>::iterator k = crep->m_getters.find(key);
1315 #ifndef LUABIND_NO_ERROR_CHECKING
1317 if (k != crep->m_getters.end())
1320 std::string msg = "cannot set property '";
1321 msg += crep->name();
1322 msg += ".";
1323 msg += key;
1324 msg += "', because it's read only";
1325 lua_pushstring(L, msg.c_str());
1327 lua_error(L);
1330 #endif
1332 detail::getref(L, obj->lua_table_ref());
1333 lua_replace(L, 1);
1334 lua_settable(L, 1);
1336 else
1338 // the name is a data member
1339 j->second.func(L, j->second.pointer_offset);
1342 return 0;
1345 int luabind::detail::class_rep::static_class_gettable(lua_State* L)
1347 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1349 // this has changed! c++ classes now also store their methods in the table
1350 // if (crep->get_class_type() == class_rep::lua_class)
1352 detail::getref(L, crep->m_table_ref);
1353 lua_pushvalue(L, 2);
1354 lua_gettable(L, -2);
1355 if (!lua_isnil(L, -1)) return 1;
1356 else lua_pop(L, 2);
1359 const char* key = lua_tostring(L, 2);
1361 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1362 if (i != crep->m_methods.end())
1364 // the name is a method, return it
1365 lua_pushlightuserdata(L, &i->second);
1366 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1367 return 1;
1370 #ifndef LUABIND_NO_ERROR_CHECKING
1372 std::map<const char*, int, ltstr>::const_iterator j = crep->m_static_constants.find(key);
1374 if (j != crep->m_static_constants.end())
1376 lua_pushnumber(L, j->second);
1377 return 1;
1381 std::string msg = "no static '";
1382 msg += key;
1383 msg += "' in class '";
1384 msg += crep->name();
1385 msg += "'";
1386 lua_pushstring(L, msg.c_str());
1388 lua_error(L);
1390 #endif
1392 return 0;
1395 bool luabind::detail::is_class_rep(lua_State* L, int index)
1397 if (lua_getmetatable(L, index) == 0) return false;
1399 lua_pushstring(L, "__luabind_classrep");
1400 lua_gettable(L, -2);
1401 if (lua_toboolean(L, -1))
1403 lua_pop(L, 2);
1404 return true;
1407 lua_pop(L, 2);
1408 return false;
1411 void luabind::detail::finalize(lua_State* L, class_rep* crep)
1413 if (crep->get_class_type() != class_rep::lua_class) return;
1415 // lua_pushvalue(L, -1); // copy the object ref
1416 detail::getref(L, crep->table_ref());
1417 lua_pushstring(L, "__finalize");
1418 lua_gettable(L, -2);
1419 lua_remove(L, -2);
1421 if (lua_isnil(L, -1))
1423 lua_pop(L, 1);
1425 else
1427 lua_pushvalue(L, -2);
1428 lua_call(L, 1, 0);
1431 for (std::vector<class_rep::base_info>::const_iterator
1432 i = crep->bases().begin(); i != crep->bases().end(); ++i)
1434 if (i->base) finalize(L, i->base);
1438 void* luabind::detail::class_rep::convert_to(LUABIND_TYPE_INFO target_type, const object_rep* obj, void* target_memory) const
1440 // TODO: since this is a member function, we don't have to use the accesor functions for
1441 // the types and the extractor
1443 int steps = 0;
1444 int offset = 0;
1445 if (!(LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), target_type))
1446 && !(LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), target_type)))
1448 steps = implicit_cast(this, target_type, offset);
1451 // should never be called with a type that can't be cast
1452 assert((steps >= 0) && "internal error, please report");
1454 if (LUABIND_TYPE_INFO_EQUAL(target_type, holder_type()))
1456 // if the type we are trying to convert to is the holder_type
1457 // it means that his crep has a holder_type (since it would have
1458 // been invalid otherwise, and T cannot be invalid). It also means
1459 // that we need no conversion, since the holder_type is what the
1460 // object points to.
1461 return obj->ptr();
1464 if (LUABIND_TYPE_INFO_EQUAL(target_type, const_holder_type()))
1466 if (obj->flags() & object_rep::constant)
1468 // we are holding a constant
1469 return obj->ptr();
1471 else
1473 // we are holding a non-constant, we need to convert it
1474 // to a const_holder.
1475 m_const_converter(obj->ptr(), target_memory);
1476 return target_memory;
1480 void* raw_pointer;
1482 if (has_holder())
1484 // this means that we have a holder type where the
1485 // raw-pointer needs to be extracted
1486 raw_pointer = extractor()(obj->ptr());
1488 else
1490 raw_pointer = obj->ptr();
1493 return static_cast<char*>(raw_pointer) + offset;
1496 void luabind::detail::class_rep::cache_operators(lua_State* L)
1498 m_operator_cache = 0x1;
1500 for (int i = 0; i < number_of_operators; ++i)
1502 getref(L, table_ref());
1503 lua_pushstring(L, get_operator_name(i));
1504 lua_rawget(L, -2);
1506 if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1);
1508 lua_pop(L, 2);
1512 bool luabind::detail::class_rep::has_operator_in_lua(lua_State* L, int id)
1514 if ((m_operator_cache & 0x1) == 0)
1515 cache_operators(L);
1517 const int mask = 1 << (id + 1);
1519 return (m_operator_cache & mask) != 0;
1522 void luabind::detail::class_rep::add_method(lua_State* L, const char* name, detail::method_rep& m)
1524 detail::getref(L, table_ref());
1525 lua_pushstring(L, name);
1526 lua_gettable(L, -2);
1528 if (lua_isnil(L, -1) || !lua_iscfunction(L, -1))
1530 lua_pop(L, 1);
1531 lua_pushstring(L, name);
1532 lua_pushlightuserdata(L, const_cast<void*>((const void*)&m));
1533 lua_pushcclosure(L, function_dispatcher, 1);
1534 lua_settable(L, -3);
1535 lua_pop(L, 1);
1537 else
1539 lua_getupvalue(L, -1, 1);
1540 method_rep* inherited = static_cast<method_rep*>(lua_touserdata(L, -1));
1542 for (std::vector<overload_rep>::const_iterator i = inherited->overloads().begin();
1543 i != inherited->overloads().end(); ++i)
1545 m.add_overload(*i);
1548 detail::getref(L, table_ref());
1549 lua_pushstring(L, name);
1550 lua_pushlightuserdata(L, const_cast<void*>((const void*)&m));
1551 lua_pushcclosure(L, function_dispatcher, 1);
1552 lua_settable(L, -3);
1553 lua_pop(L, 4);
1557 const class_rep::property_map& luabind::detail::class_rep::properties() const
1559 return m_getters;