*** empty log message ***
[luabind.git] / src / class_rep.cpp
blobe85e6cc081e3cec66760ca007829fb0c2185618a
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 extern "C"
25 #include "lua.h"
28 #include <luabind/luabind.hpp>
29 #include <utility>
31 using namespace luabind::detail;
34 #ifndef LUABIND_NO_ERROR_CHECKING
36 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)
38 std::string s;
39 for (; start != end; ++start)
41 s += name;
42 (*start)->get_signature(L, s);
43 s += "\n";
45 return s;
48 #endif
51 luabind::detail::class_rep::class_rep(LUABIND_TYPE_INFO type
52 , const char* name
53 , lua_State* L
54 , void(*destructor)(void*)
55 , void(*const_holder_destructor)(void*)
56 , LUABIND_TYPE_INFO holder_type
57 , LUABIND_TYPE_INFO const_holder_type
58 , void*(*extractor)(void*)
59 , const void*(*const_extractor)(void*)
60 , void(*const_converter)(void*,void*)
61 , void(*construct_holder)(void*,void*)
62 , void(*construct_const_holder)(void*,void*)
63 , int holder_size
64 , int holder_alignment)
66 : m_type(type)
67 , m_holder_type(holder_type)
68 , m_const_holder_type(const_holder_type)
69 , m_extractor(extractor)
70 , m_const_extractor(const_extractor)
71 , m_const_converter(const_converter)
72 , m_construct_holder(construct_holder)
73 , m_construct_const_holder(construct_const_holder)
74 , m_holder_size(holder_size)
75 , m_holder_alignment(holder_alignment)
76 , m_name(name)
77 , m_table_ref(LUA_NOREF)
78 , m_class_type(cpp_class)
79 , m_destructor(destructor)
80 , m_const_holder_destructor(const_holder_destructor)
81 , m_operator_cache(0)
83 assert(m_holder_alignment >= 1 && "internal error");
85 class_registry* r = class_registry::get_registry(L);
86 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
88 detail::getref(L, r->cpp_class());
89 lua_setmetatable(L, -2);
91 lua_pushvalue(L, -1); // duplicate our user data
92 m_self_ref = detail::ref(L); // pop one of them
94 m_instance_metatable = r->cpp_instance();
97 luabind::detail::class_rep::class_rep(lua_State* L, const char* name)
98 : m_type(LUABIND_INVALID_TYPE_INFO)
99 , m_holder_type(LUABIND_INVALID_TYPE_INFO)
100 , m_const_holder_type(LUABIND_INVALID_TYPE_INFO)
101 , m_extractor(0)
102 , m_const_extractor(0)
103 , m_const_converter(0)
104 , m_construct_holder(0)
105 , m_construct_const_holder(0)
106 , m_holder_size(0)
107 , m_holder_alignment(1)
108 , m_class_type(lua_class)
109 , m_destructor(0)
110 , m_const_holder_destructor(0)
111 , m_operator_cache(0)
113 #ifndef LUABIND_DONT_COPY_STRINGS
114 m_strings.push_back(detail::dup_string(name));
115 m_name = m_strings.back();
116 #else
117 m_name = name;
118 #endif
119 lua_newtable(L);
120 m_table_ref = detail::ref(L);
122 class_registry* r = class_registry::get_registry(L);
123 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
125 detail::getref(L, r->lua_class());
126 lua_setmetatable(L, -2);
127 lua_pushvalue(L, -1); // duplicate our user data
128 m_self_ref = detail::ref(L); // pop one of them
130 m_instance_metatable = r->lua_instance();
133 luabind::detail::class_rep::~class_rep()
135 #ifndef LUABIND_DONT_COPY_STRINGS
136 for (std::vector<char*>::iterator i = m_strings.begin();
137 i != m_strings.end(); ++i)
139 delete[] *i;
141 #endif
144 std::pair<void*,void*>
145 luabind::detail::class_rep::allocate(lua_State* L) const
147 const int overlap = sizeof(object_rep)&(m_holder_alignment-1);
148 const int padding = overlap==0?0:m_holder_alignment-overlap;
149 const int size = sizeof(object_rep) + padding + m_holder_size;
151 char* mem = static_cast<char*>(lua_newuserdata(L, size));
152 char* ptr = mem + sizeof(object_rep) + padding;
154 return std::pair<void*,void*>(mem,ptr);
157 int luabind::detail::class_rep::gettable(lua_State* L)
159 if (lua_isnil(L, 2))
161 lua_pushnil(L);
162 return 1;
165 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
167 // we have to ignore the first argument since this may point to
168 // a method that is not present in this class (but in a subclass)
169 const char* key = lua_tostring(L, 2);
171 if (key && !strcmp(key, "__ok"))
173 class_rep* crep = obj->crep();
175 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
176 : obj->ptr();
178 lua_pushboolean(L, p != 0);
179 return 1;
182 std::map<const char*, method_rep, ltstr>::iterator i = m_methods.find(key);
184 if (i != m_methods.end())
186 // the name is a method, return it
187 lua_pushlightuserdata(L, &i->second);
188 lua_pushcclosure(L, function_dispatcher, 1);
189 return 1;
192 std::map<const char*, callback, ltstr>::iterator j = m_getters.find(key);
193 if (j != m_getters.end())
195 // the name is a data member
196 return j->second.func(L, j->second.pointer_offset);
199 lua_pushnil(L);
200 return 1;
203 // called from the metamethod for __newindex
204 // the object pointer is passed on the lua stack
205 bool luabind::detail::class_rep::settable(lua_State* L)
207 if (lua_isnil(L, 2))
209 return false;
212 // we have to ignore the first argument since this may point to
213 // a method that is not present in this class (but in a subclass)
214 const char* key = lua_tostring(L, 2);
215 std::map<const char*, callback, ltstr>::iterator j = m_setters.find(key);
216 if (j != m_setters.end())
218 // the name is a data member
219 j->second.func(L, j->second.pointer_offset);
220 return true;
223 return false; // false means that we don't have a member with the given name
226 int class_rep::gettable_dispatcher(lua_State* L)
228 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
229 return obj->crep()->gettable(L);
232 // this is called as __newindex metamethod on every instance of this class
233 int luabind::detail::class_rep::settable_dispatcher(lua_State* L)
235 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
237 bool success = obj->crep()->settable(L);
239 #ifndef LUABIND_NO_ERROR_CHECKING
241 if (!success)
243 // this block is needed to make sure the std::string is destructed before
244 // lua_error() is called
245 #ifdef BOOST_MSVC
247 // msvc has a bug which deletes the string twice, that's
248 // why we have to create it on the heap
249 std::string* msg = new std::string("cannot set attribute '");
250 *msg += obj->crep()->m_name;
251 *msg += ".";
252 *msg += lua_tostring(L, -2);
253 *msg += "'";
254 lua_pushstring(L, msg->c_str());
255 delete msg;
257 #else
259 std::string msg = "cannot set attribute '";
260 msg += obj->crep()->m_name;
261 msg += ".";
262 msg += lua_tostring(L, -2);
263 msg += "'";
264 lua_pushstring(L, msg.c_str());
266 #endif
267 lua_error(L);
270 #endif
272 return 0;
276 int luabind::detail::class_rep::operator_dispatcher(lua_State* L)
278 int id = static_cast<int>(lua_tonumber(L, lua_upvalueindex(1)));
280 int operand_id = 0;
282 object_rep* operand[2];
283 for (int i = 0; i < 2; ++i)
284 operand[i] = detail::is_class_object(L, i + 1);
286 // we cannot compare the types here, we have to compare the pointers of the class_reps
287 // since all lua-classes have the same type (LUABIND_INVALID_TYPE_INFO)
288 if (operand[0] && operand[1])
289 if (operand[0]->crep() == operand[1]->crep()) operand[1] = 0;
291 std::vector<operator_callback>* overloads[2];
292 for (int i = 0; i < 2; ++i)
293 if (operand[i]) overloads[i] = &operand[i]->crep()->m_operators[id]; else overloads[i] = 0;
295 std::size_t num_overloads[2];
296 for (int i = 0; i < 2; ++i)
297 if (overloads[i]) num_overloads[i] = overloads[i]->size(); else num_overloads[i] = 0;
299 for (int i = 0; i < 2; ++i)
300 if (operand[i] && operand[i]->crep()->get_class_type() == class_rep::lua_class)
302 /* // if this is a lua class we have to
303 // look in its table to see if there's
304 // any overload of this operator
305 detail::getref(L, operand[i]->crep()->table_ref());
306 lua_pushstring(L, get_operator_name(id));
307 lua_rawget(L, -2);
308 // if we have tha operator, set num_overloads to 1
309 if (lua_isfunction(L, -1)) num_overloads[i] = 1;
310 lua_pop(L, 2);*/
312 if (operand[i]->crep()->has_operator_in_lua(L, id))
313 num_overloads[i] = 1;
316 bool ambiguous = false;
317 int match_index = -1;
318 int min_match = std::numeric_limits<int>::max();
320 #ifdef LUABIND_NO_ERROR_CHECKING
322 if (num_overloads[0] == 1 && num_overloads[1] == 0)
324 operand_id = 0;
325 match_index = 0;
327 else if (num_overloads[0] == 0 && num_overloads[1] == 1)
329 operand_id = 1;
330 match_index = 0;
332 else
335 #endif
337 int num_params = lua_gettop(L);
339 // have look at the right operand.
340 // if the right operand is a class and
341 // not the same class as this, we have to
342 // try to match it's operators too
343 for (int i = 0; i < 2; ++i)
345 if (num_overloads[i])
347 if (operand[i]->crep()->get_class_type() == class_rep::lua_class)
349 // if this is a lua class
350 // and num_overloads is > 0
351 // it means that it has implemented
352 // this operator. Set match_index to
353 // 0 to signal that this operand has
354 // an overload, but leave the min_match
355 // at int-max to mark it as a last resort
356 operand_id = i;
357 if (match_index == -1) match_index = 0;
359 else if (find_best_match(
361 , &overloads[i]->front()
362 , overloads[i]->size()
363 , sizeof(operator_callback)
364 , ambiguous
365 , min_match
366 , match_index
367 , num_params))
369 operand_id = i;
375 #ifdef LUABIND_NO_ERROR_CHECKING
379 #else
381 if (match_index == -1)
383 // this block is needed to make sure the std::string is destructed before
384 // lua_error() is called
386 std::string msg = "no operator ";
387 msg += get_operator_symbol(id);
388 msg += " matched the arguments (";
389 msg += stack_content_by_name(L, 1);
390 msg += ")\ncandidates are:\n";
392 for (int i = 0; i < 2; ++i)
394 if (overloads[i])
396 msg += get_overload_signatures(
398 , overloads[i]->begin()
399 , overloads[i]->end()
400 , get_operator_symbol(id));
402 else
404 // if num_overloads is > 0 it would mean that this is
405 // a lua class with this operator overloaded. And if
406 // that's the case, it should always match (and if an
407 // operator matches, we never come here).
408 assert(num_overloads[i] == 0 && "internal error");
412 lua_pushstring(L, msg.c_str());
414 lua_error(L);
416 else if (ambiguous)
418 // this block is needed to make sure the std::string is destructed before
419 // lua_error() is called
421 std::string msg = "call of overloaded operator ";
422 msg += get_operator_symbol(id);
423 msg += " (";
424 msg += stack_content_by_name(L, 1);
425 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
427 std::vector<const overload_rep_base*> candidates;
428 if (overloads[0])
429 find_exact_match(L, &overloads[0]->front(), overloads[0]->size(), sizeof(operator_callback), min_match, num_params, candidates);
431 if (overloads[1])
432 find_exact_match(L, &overloads[1]->front(), overloads[1]->size(), sizeof(operator_callback), min_match, num_params, candidates);
434 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), get_operator_symbol(id));
436 lua_pushstring(L, msg.c_str());
438 lua_error(L);
441 #endif
443 if (operand[operand_id]->crep()->get_class_type() == class_rep::lua_class)
445 detail::getref(L, operand[operand_id]->crep()->table_ref());
446 lua_pushstring(L, get_operator_name(id));
447 lua_rawget(L, -2);
448 lua_insert(L, -4); // move the function to the bottom
449 lua_pop(L, 1); // remove the table
450 lua_call(L, 2, 1);
451 return 1;
453 else
455 return (*overloads[operand_id])[match_index].call(L);
459 // this is called as metamethod __call on the class_rep.
460 int luabind::detail::class_rep::constructor_dispatcher(lua_State* L)
462 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
463 construct_rep* rep = &crep->m_constructor;
465 bool ambiguous = false;
466 int match_index = -1;
467 int min_match = std::numeric_limits<int>::max();
468 bool found;
470 #ifdef LUABIND_NO_ERROR_CHECKING
472 if (rep->overloads.size() == 1)
474 match_index = 0;
476 else
479 #endif
481 int num_params = lua_gettop(L) - 1;
482 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
484 #ifdef LUABIND_NO_ERROR_CHECKING
487 #else
489 if (!found)
491 // this block is needed to make sure the std::string is destructed before
492 // lua_error() is called
494 std::string msg = "no constructor of '";
495 msg += crep->name();
496 msg += "' matched the arguments (";
497 msg += stack_content_by_name(L, 2);
498 msg += ")\n candidates are:\n";
500 msg += get_overload_signatures(L, rep->overloads.begin(), rep->overloads.end(), crep->name());
502 lua_pushstring(L, msg.c_str());
504 lua_error(L);
506 else if (ambiguous)
508 // this block is needed to make sure the std::string is destructed before
509 // lua_error() is called
511 std::string msg = "call of overloaded constructor '";
512 msg += crep->m_name;
513 msg += "(";
514 msg += stack_content_by_name(L, 2);
515 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
517 std::vector<const overload_rep_base*> candidates;
518 find_exact_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), min_match, num_params, candidates);
519 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), crep->name());
521 lua_pushstring(L, msg.c_str());
523 lua_error(L);
526 #endif
528 #ifndef LUABIND_NO_EXCEPTIONS
533 #endif
535 void* object_ptr = rep->overloads[match_index].construct(L);
537 void* obj_rep;
538 void* held;
540 boost::tie(obj_rep,held) = crep->allocate(L);
542 if (crep->has_holder())
544 crep->m_construct_holder(held, object_ptr);
545 object_ptr = held;
547 new(obj_rep) object_rep(object_ptr, crep, object_rep::owner, crep->destructor());
549 detail::getref(L, crep->m_instance_metatable);
550 lua_setmetatable(L, -2);
551 return 1;
553 #ifndef LUABIND_NO_EXCEPTIONS
557 catch(const std::exception& e)
559 lua_pushstring(L, e.what());
561 catch(const char* s)
563 lua_pushstring(L, s);
565 catch(...)
568 std::string msg = crep->name();
569 msg += "() threw an exception";
570 lua_pushstring(L, msg.c_str());
574 // we can only reach this line if an exception was thrown
575 lua_error(L);
576 return 0; // will never be reached
578 #endif
582 // TODO: remove
584 int luabind::detail::class_rep::implicit_cast(const class_rep* from, const class_rep* to, int& pointer_offset)
586 int offset = 0;
587 if (LUABIND_TYPE_INFO_EQUAL(from->type(), to->type())) return 0;
589 for (std::vector<class_rep::base_info>::const_iterator i = from->bases().begin(); i != from->bases().end(); ++i)
591 int steps = implicit_cast(i->base, to, offset);
592 pointer_offset = offset + i->pointer_offset;
593 if (steps >= 0) return steps + 2;
595 return -1;
600 // the functions dispatcher assumes the following:
601 // there is one upvalue that points to the method_rep that this dispatcher is to call
602 // the first parameter on the lua stack is an object_rep that points to the object the
603 // call is being made on
604 int luabind::detail::class_rep::function_dispatcher(lua_State* L)
606 method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
607 object_rep* obj = reinterpret_cast<object_rep*>(lua_touserdata(L, 1));
609 #ifndef LUABIND_NO_ERROR_CHECKING
611 if (is_class_object(L, 1) == 0)
614 std::string msg = "No self reference given as first parameter to member function '";
615 msg += rep->crep->name();
616 msg += ":";
617 msg += rep->name;
618 msg += "'. Have you used '.' instead of ':'?";
620 lua_pushstring(L, msg.c_str());
622 lua_error(L);
625 int p;
626 if (implicit_cast(obj->crep(), rep->crep->type(), p) < 0)
629 std::string msg = "invalid self reference given to '";
630 msg += rep->crep->name();
631 msg += ":";
632 msg += rep->name;
633 msg += "'";
634 lua_pushstring(L, msg.c_str());
636 lua_error(L);
639 #endif
641 bool ambiguous = false;
642 int match_index = -1;
643 int min_match = std::numeric_limits<int>::max();
644 bool found;
646 #ifdef LUABIND_NO_ERROR_CHECKING
647 if (rep->overloads().size() == 1)
649 match_index = 0;
651 else
653 #endif
655 int num_params = lua_gettop(L) - 1;
656 found = find_best_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), ambiguous, min_match, match_index, num_params);
658 #ifdef LUABIND_NO_ERROR_CHECKING
662 #else
664 if (!found)
667 std::string msg = "no overload of '";
668 msg += rep->crep->name();
669 msg += ":";
670 msg += rep->name;
671 msg += "' matched the arguments (";
672 msg += stack_content_by_name(L, 2);
673 msg += ")\ncandidates are:\n";
675 std::string function_name;
676 function_name += rep->crep->name();
677 function_name += ":";
678 function_name += rep->name;
680 msg += get_overload_signatures(L, rep->overloads().begin(), rep->overloads().end(), function_name);
682 lua_pushstring(L, msg.c_str());
684 lua_error(L);
686 else if (ambiguous)
689 std::string msg = "call of overloaded '";
690 msg += rep->crep->name();
691 msg += ":";
692 msg += rep->name;
693 msg += "(";
694 msg += stack_content_by_name(L, 2);
695 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
697 std::vector<const overload_rep_base*> candidates;
698 find_exact_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), min_match, num_params, candidates);
700 std::string function_name;
701 function_name += rep->crep->name();
702 function_name += ":";
703 function_name += rep->name;
705 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), function_name);
707 lua_pushstring(L, msg.c_str());
709 lua_error(L);
712 #endif
714 #ifndef LUABIND_NO_EXCEPTIONS
719 #endif
721 const overload_rep& o = rep->overloads()[match_index];
722 return o.call(L, *obj);
724 #ifndef LUABIND_NO_EXCEPTIONS
727 catch(const std::exception& e)
729 lua_pushstring(L, e.what());
731 catch (const char* s)
733 lua_pushstring(L, s);
735 catch(...)
737 std::string msg = rep->crep->name();
738 msg += ":";
739 msg += rep->name;
740 msg += "() threw an exception";
741 lua_pushstring(L, msg.c_str());
743 // we can only reach this line if an exception was thrown
744 lua_error(L);
745 return 0; // will never be reached
747 #endif
751 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo)
753 // If you hit this assert you are deriving from a type that is not registered
754 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
755 // Please note that if you don't need to have access to the base class or the
756 // conversion from the derived class to the base class, you don't need
757 // to tell luabind that it derives.
758 assert(binfo.base && "You cannot derive from an unregistered type");
760 class_rep* bcrep = binfo.base;
762 // import all functions from the base
763 for (std::map<const char*, method_rep, ltstr>::const_iterator i = bcrep->m_methods.begin();
764 i != bcrep->m_methods.end(); ++i)
766 // If we would assume that our base class will not be garbage collected until
767 // this class is collected, we wouldn't had to copy these strings.
768 #ifndef LUABIND_DONT_COPY_STRINGS
769 m_strings.push_back(dup_string(i->first));
770 method_rep& m = m_methods[m_strings.back()];
771 #else
772 method_rep& m = m_methods[i->first];
773 #endif
774 m.name = i->first;
775 m.crep = this;
777 for (std::vector<overload_rep>::const_iterator j = i->second.overloads().begin();
778 j != i->second.overloads().end(); ++j)
780 overload_rep o = *j;
781 o.add_offset(binfo.pointer_offset);
782 m.add_overload(o);
786 // import all getters from the base
787 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_getters.begin();
788 i != bcrep->m_getters.end(); ++i)
790 #ifndef LUABIND_DONT_COPY_STRINGS
791 m_strings.push_back(dup_string(i->first));
792 callback& m = m_getters[m_strings.back()];
793 #else
794 callback& m = m_getters[i->first];
795 #endif
796 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
797 m.func = i->second.func;
800 // import all setters from the base
801 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_setters.begin();
802 i != bcrep->m_setters.end(); ++i)
804 #ifndef LUABIND_DONT_COPY_STRINGS
805 // TODO: optimize this by not copying the string if it already exists in m_setters.
806 // This goes for m_getters, m_static_constants and m_functions too. Both here
807 // in add_base() and in the add_function(), add_getter() ... functions.
808 m_strings.push_back(dup_string(i->first));
809 callback& m = m_setters[m_strings.back()];
810 #else
811 callback& m = m_setters[i->first];
812 #endif
813 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
814 m.func = i->second.func;
817 // import all static constants
818 for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin();
819 i != bcrep->m_static_constants.end(); ++i)
821 #ifndef LUABIND_DONT_COPY_STRINGS
822 m_strings.push_back(dup_string(i->first));
823 int& v = m_static_constants[m_strings.back()];
824 #else
825 int& v = m_static_constants[i->first];
826 #endif
827 v = i->second;
830 // import all operators
831 for (int i = 0; i < number_of_operators; ++i)
833 for (std::vector<operator_callback>::const_iterator j = bcrep->m_operators[i].begin();
834 j != bcrep->m_operators[i].end(); ++j)
835 m_operators[i].push_back(*j);
838 // also, save the baseclass info to be used for typecasts
839 m_bases.push_back(binfo);
842 void luabind::detail::class_rep::add_function(const char* name, const overload_rep& o)
845 #ifdef LUABIND_DONT_COPY_STRINGS
846 detail::method_rep& method = m_methods[name];
847 method.name = name;
848 #else
849 m_strings.push_back(dup_string(name));
850 detail::method_rep& method = m_methods[m_strings.back()];
851 method.name = m_strings.back();
852 #endif
854 method.add_overload(o);
855 method.crep = this;
858 void luabind::detail::class_rep::add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
860 callback c;
861 c.func = g;
862 c.pointer_offset = 0;
863 #ifndef LUABIND_DONT_COPY_STRINGS
864 m_strings.push_back(dup_string(name));
865 m_getters[m_strings.back()] = c;
866 #else
867 m_getters[name] = c;
868 #endif
871 void luabind::detail::class_rep::add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
873 callback c;
874 c.func = s;
875 c.pointer_offset = 0;
876 #ifndef LUABIND_DONT_COPY_STRINGS
877 m_strings.push_back(dup_string(name));
878 m_setters[m_strings.back()] = c;
879 #else
880 m_setters[name] = c;
881 #endif
884 #ifndef LUABIND_NO_ERROR_CHECKING
885 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)
886 #else
887 void luabind::detail::class_rep::add_operator(lua_State*, int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
888 #endif
890 operator_callback o;
891 o.set_fun(func);
892 o.set_match_fun(matcher);
893 o.set_arity(arity);
895 #ifndef LUABIND_NO_ERROR_CHECKING
897 o.set_sig_fun(sig);
899 #endif
900 m_operators[op_id].push_back(o);
903 void luabind::detail::class_rep::add_static_constant(const char* name, int val)
905 #ifndef LUABIND_DONT_COPY_STRINGS
906 m_strings.push_back(dup_string(name));
907 m_static_constants[m_strings.back()] = val;
908 #else
909 m_static_constants[name] = val;
910 #endif
913 int luabind::detail::class_rep::super_callback(lua_State* L)
915 int args = lua_gettop(L);
917 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, lua_upvalueindex(2)));
918 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
919 class_rep* base = crep->bases()[0].base;
921 if (base->get_class_type() == class_rep::lua_class)
923 if (base->bases().empty())
925 obj->set_flags(obj->flags() & ~object_rep::call_super);
927 lua_pushstring(L, "super");
928 lua_pushnil(L);
929 lua_settable(L, LUA_GLOBALSINDEX);
931 else
933 lua_pushstring(L, "super");
934 lua_pushlightuserdata(L, base);
935 lua_pushvalue(L, lua_upvalueindex(2));
936 lua_pushcclosure(L, super_callback, 2);
937 lua_settable(L, LUA_GLOBALSINDEX);
940 detail::getref(L, base->table_ref());
941 lua_pushstring(L, "__init");
942 lua_gettable(L, -2);
943 lua_insert(L, 1);
944 lua_pop(L, 1);
946 lua_pushvalue(L, lua_upvalueindex(2));
947 lua_insert(L, 2);
949 lua_call(L, args + 1, 0);
951 // TODO: instead of clearing the global variable "super"
952 // store it temporarily in the registry. maybe we should
953 // have some kind of warning if the super global is used?
954 lua_pushstring(L, "super");
955 lua_pushnil(L);
956 lua_settable(L, LUA_GLOBALSINDEX);
958 else
960 obj->set_flags(obj->flags() & ~object_rep::call_super);
962 // we need to push some garbage at index 1 to make the construction work
963 lua_pushboolean(L, 1);
964 lua_insert(L, 1);
966 construct_rep* rep = &base->m_constructor;
968 bool ambiguous = false;
969 int match_index = -1;
970 int min_match = std::numeric_limits<int>::max();
971 bool found;
973 #ifdef LUABIND_NO_ERROR_CHECKING
975 if (rep->overloads.size() == 1)
977 match_index = 0;
979 else
982 #endif
984 int num_params = lua_gettop(L) - 1;
985 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
987 #ifdef LUABIND_NO_ERROR_CHECKING
991 #else
993 if (!found)
996 std::string msg = "no constructor of '";
997 msg += base->m_name;
998 msg += "' matched the arguments (";
999 msg += stack_content_by_name(L, 2);
1000 msg += ")";
1001 lua_pushstring(L, msg.c_str());
1003 lua_error(L);
1005 else if (ambiguous)
1008 std::string msg = "call of overloaded constructor '";
1009 msg += base->m_name;
1010 msg += "(";
1011 msg += stack_content_by_name(L, 2);
1012 msg += ")' is ambiguous";
1013 lua_pushstring(L, msg.c_str());
1015 lua_error(L);
1018 // TODO: should this be a warning or something?
1020 // since the derived class is a lua class
1021 // it may have reimplemented virtual functions
1022 // therefore, we have to instantiate the Basewrapper
1023 // if there is no basewrapper, throw a run-time error
1024 if (!rep->overloads[match_index].has_wrapped_construct())
1027 std::string msg = "Cannot derive from C++ class '";
1028 msg += base->name();
1029 msg += "'. It does not have a wrapped type";
1030 lua_pushstring(L, msg.c_str());
1032 lua_error(L);
1035 #endif
1037 #ifndef LUABIND_NO_EXCEPTIONS
1042 #endif
1044 if (!rep->overloads[match_index].has_wrapped_construct())
1046 // if the type doesn't have a wrapped type, use the ordinary constructor
1047 obj->set_object(rep->overloads[match_index].construct(L));
1049 else
1051 // get reference to lua object
1052 lua_pushvalue(L, lua_upvalueindex(2));
1053 int ref = detail::ref(L);
1054 obj->set_object(rep->overloads[match_index].construct_wrapped(L, ref));
1056 // TODO: is the wrapped type destructed correctly?
1057 // it should, since the destructor is either the wrapped type's
1058 // destructor or the base type's destructor, depending on wether
1059 // the type has a wrapped type or not.
1060 obj->set_destructor(base->destructor());
1061 return 0;
1063 #ifndef LUABIND_NO_EXCEPTIONS
1066 catch(const std::exception& e)
1068 lua_pushstring(L, e.what());
1070 catch(const char* s)
1072 lua_pushstring(L, s);
1074 catch(...)
1076 std::string msg = base->m_name;
1077 msg += "() threw an exception";
1078 lua_pushstring(L, msg.c_str());
1080 // can only be reached if an exception was thrown
1081 lua_error(L);
1082 #endif
1085 return 0;
1091 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L)
1093 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1094 detail::getref(L, crep->m_table_ref);
1095 lua_replace(L, 1);
1096 lua_rawset(L, -3);
1098 crep->m_operator_cache = 0; // invalidate cache
1100 return 0;
1103 int luabind::detail::class_rep::construct_lua_class_callback(lua_State* L)
1105 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1107 int args = lua_gettop(L);
1109 // lua stack: crep <arguments>
1111 lua_newtable(L);
1112 int ref = detail::ref(L);
1114 bool has_bases = !crep->bases().empty();
1116 if (has_bases)
1118 lua_pushstring(L, "super");
1119 lua_pushvalue(L, 1); // crep
1122 // lua stack: crep <arguments> "super" crep
1123 // or
1124 // lua stack: crep <arguments>
1126 // if we have a baseclass we set the flag to say that the super has not yet been called
1127 // we will use this flag later to check that it actually was called from __init()
1128 int flags = object_rep::lua_class | object_rep::owner | (has_bases ? object_rep::call_super : 0);
1130 void* obj_ptr = lua_newuserdata(L, sizeof(object_rep));
1131 new(obj_ptr) object_rep(crep, flags, ref);
1133 detail::getref(L, crep->metatable_ref());
1134 lua_setmetatable(L, -2);
1136 // lua stack: crep <arguments> "super" crep obj_ptr
1137 // or
1138 // lua stack: crep <arguments> obj_ptr
1140 if (has_bases) lua_pushvalue(L, -1); // obj_ptr
1141 lua_replace(L, 1); // obj_ptr
1143 // lua stack: obj_ptr <arguments> "super" crep obj_ptr
1144 // or
1145 // lua stack: obj_ptr <arguments>
1147 if (has_bases)
1149 lua_pushcclosure(L, super_callback, 2);
1150 // lua stack: crep <arguments> "super" function
1151 lua_settable(L, LUA_GLOBALSINDEX);
1154 // lua stack: crep <arguments>
1156 lua_pushvalue(L, 1);
1157 lua_insert(L, 1);
1159 detail::getref(L, crep->table_ref());
1160 lua_pushstring(L, "__init");
1161 lua_gettable(L, -2);
1163 #ifndef LUABIND_NO_ERROR_CHECKING
1165 // TODO: should this be a run-time error?
1166 // maybe the default behavior should be to just call
1167 // the base calss' constructor. We should register
1168 // the super callback funktion as __init
1169 if (!lua_isfunction(L, -1))
1172 std::string msg = crep->name();
1173 msg += ":__init is not defined";
1174 lua_pushstring(L, msg.c_str());
1176 lua_error(L);
1179 #endif
1181 lua_insert(L, 2); // function first on stack
1182 lua_pop(L, 1);
1183 // TODO: lua_call may invoke longjump! make sure we don't have any memory leaks!
1184 // we don't have any stack objects here
1185 lua_call(L, args, 0);
1187 #ifndef LUABIND_NO_ERROR_CHECKING
1189 object_rep* obj = static_cast<object_rep*>(obj_ptr);
1190 if (obj->flags() & object_rep::call_super)
1192 lua_pushstring(L, "derived class must call super on base");
1193 lua_error(L);
1196 #endif
1198 return 1;
1201 // called from the metamethod for __index
1202 // obj is the object pointer
1203 int luabind::detail::class_rep::lua_class_gettable(lua_State* L)
1205 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1206 class_rep* crep = obj->crep();
1208 #ifndef LUABIND_NO_ERROR_CHECKING
1210 if (obj->flags() & object_rep::call_super)
1212 lua_pushstring(L, "derived class must call super on base");
1213 lua_error(L);
1216 #endif
1218 // we have to ignore the first argument since this may point to
1219 // a method that is not present in this class (but in a subclass)
1220 const char* key = lua_tostring(L, 2);
1222 if (key && !strcmp(key, "__ok"))
1224 class_rep* crep = obj->crep();
1226 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
1227 : obj->ptr();
1229 lua_pushboolean(L, p != 0);
1230 return 1;
1233 detail::getref(L, obj->lua_table_ref());
1234 lua_pushvalue(L, 2);
1235 lua_gettable(L, -2);
1237 if (!lua_isnil(L, -1))
1239 lua_remove(L, -2); // remove table
1240 return 1;
1243 lua_pop(L, 2);
1245 detail::getref(L, crep->table_ref());
1246 lua_pushvalue(L, 2);
1247 lua_gettable(L, -2);
1249 if (!lua_isnil(L, -1))
1251 lua_remove(L, -2); // more table
1252 return 1;
1255 lua_pop(L, 2);
1257 if (lua_isnil(L, 2))
1259 lua_pushnil(L);
1260 return 1;
1263 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1264 if (i != crep->m_methods.end())
1266 // the name is a method, return it
1267 lua_pushlightuserdata(L, &i->second);
1268 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1269 return 1;
1272 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_getters.find(key);
1273 if (j != crep->m_getters.end())
1275 // the name is a data member
1276 return j->second.func(L, j->second.pointer_offset);
1279 lua_pushnil(L);
1280 return 1;
1283 // called from the metamethod for __newindex
1284 // obj is the object pointer
1285 int luabind::detail::class_rep::lua_class_settable(lua_State* L)
1287 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1288 class_rep* crep = obj->crep();
1290 #ifndef LUABIND_NO_ERROR_CHECKING
1292 if (obj->flags() & object_rep::call_super)
1294 // this block makes sure the std::string is destructed
1295 // before lua_error is called
1297 std::string msg = "derived class '";
1298 msg += crep->name();
1299 msg += "'must call super on base";
1300 lua_pushstring(L, msg.c_str());
1302 lua_error(L);
1305 #endif
1307 // we have to ignore the first argument since this may point to
1308 // a method that is not present in this class (but in a subclass)
1309 const char* key = lua_tostring(L, 2);
1310 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_setters.find(key);
1312 if (j == crep->m_setters.end())
1314 std::map<const char*, class_rep::callback, ltstr>::iterator k = crep->m_getters.find(key);
1316 #ifndef LUABIND_NO_ERROR_CHECKING
1318 if (k != crep->m_getters.end())
1321 std::string msg = "cannot set property '";
1322 msg += crep->name();
1323 msg += ".";
1324 msg += key;
1325 msg += "', because it's read only";
1326 lua_pushstring(L, msg.c_str());
1328 lua_error(L);
1331 #endif
1333 detail::getref(L, obj->lua_table_ref());
1334 lua_replace(L, 1);
1335 lua_settable(L, 1);
1337 else
1339 // the name is a data member
1340 j->second.func(L, j->second.pointer_offset);
1343 return 0;
1346 int luabind::detail::class_rep::static_class_gettable(lua_State* L)
1348 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
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 detail::getref(L, crep->table_ref());
1416 lua_pushstring(L, "__finalize");
1417 lua_gettable(L, -2);
1419 if (lua_isnil(L, -1))
1421 lua_pop(L, 1);
1423 else
1425 lua_pushvalue(L, -2);
1426 lua_call(L, 1, 0);
1429 for (std::vector<class_rep::base_info>::const_iterator
1430 i = crep->bases().begin(); i != crep->bases().end(); ++i)
1432 if (i->base) finalize(L, i->base);
1436 void* luabind::detail::class_rep::convert_to(LUABIND_TYPE_INFO target_type, const object_rep* obj, void* target_memory) const
1438 // TODO: since this is a member function, we don't have to use the accesor functions for
1439 // the types and the extractor
1441 int steps = 0;
1442 int offset = 0;
1443 if (!(LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), target_type))
1444 && !(LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), target_type)))
1446 steps = implicit_cast(this, target_type, offset);
1449 // should never be called with a type that can't be cast
1450 assert((steps >= 0) && "internal error, please report");
1452 if (LUABIND_TYPE_INFO_EQUAL(target_type, holder_type()))
1454 // if the type we are trying to convert to is the holder_type
1455 // it means that his crep has a holder_type (since it would have
1456 // been invalid otherwise, and T cannot be invalid). It also means
1457 // that we need no conversion, since the holder_type is what the
1458 // object points to.
1459 return obj->ptr();
1462 if (LUABIND_TYPE_INFO_EQUAL(target_type, const_holder_type()))
1464 if (obj->flags() & object_rep::constant)
1466 // we are holding a constant
1467 return obj->ptr();
1469 else
1471 // we are holding a non-constant, we need to convert it
1472 // to a const_holder.
1473 m_const_converter(obj->ptr(), target_memory);
1474 return target_memory;
1478 void* raw_pointer;
1480 if (has_holder())
1482 // this means that we have a holder type where the
1483 // raw-pointer needs to be extracted
1484 raw_pointer = extractor()(obj->ptr());
1486 else
1488 raw_pointer = obj->ptr();
1491 return static_cast<char*>(raw_pointer) + offset;
1494 void class_rep::cache_operators(lua_State* L)
1496 m_operator_cache = 0x1;
1498 for (int i = 0; i < number_of_operators; ++i)
1500 getref(L, table_ref());
1501 lua_pushstring(L, get_operator_name(i));
1502 lua_rawget(L, -2);
1504 if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1);
1506 lua_pop(L, 2);
1510 bool class_rep::has_operator_in_lua(lua_State* L, int id)
1512 if ((m_operator_cache & 0x1) == 0)
1513 cache_operators(L);
1515 const int mask = 1 << (id + 1);
1517 return m_operator_cache & mask;