Fixed the bug where enums stopped working when built with LUABIND_NO_ERROR_CHECKING...
[luabind.git] / src / class_rep.cpp
blob3f06c6ce58e4aa0cf500fc0614e29eed88620d0b
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(
36 lua_State* L
37 , std::vector<const overload_rep_base*>::iterator start
38 , std::vector<const overload_rep_base*>::iterator end
39 , std::string name)
41 std::string s;
42 for (; start != end; ++start)
44 s += name;
45 (*start)->get_signature(L, s);
46 s += "\n";
48 return s;
51 #endif
54 luabind::detail::class_rep::class_rep(LUABIND_TYPE_INFO type
55 , const char* name
56 , lua_State* L
57 , void(*destructor)(void*)
58 , void(*const_holder_destructor)(void*)
59 , LUABIND_TYPE_INFO holder_type
60 , LUABIND_TYPE_INFO const_holder_type
61 , void*(*extractor)(void*)
62 , const void*(*const_extractor)(void*)
63 , void(*const_converter)(void*,void*)
64 , void(*construct_holder)(void*,void*)
65 , void(*construct_const_holder)(void*,void*)
66 , int holder_size
67 , int holder_alignment)
69 : m_type(type)
70 , m_holder_type(holder_type)
71 , m_const_holder_type(const_holder_type)
72 , m_extractor(extractor)
73 , m_const_extractor(const_extractor)
74 , m_const_converter(const_converter)
75 , m_construct_holder(construct_holder)
76 , m_construct_const_holder(construct_const_holder)
77 , m_holder_size(holder_size)
78 , m_holder_alignment(holder_alignment)
79 , m_name(name)
80 , m_table_ref(LUA_NOREF)
81 , m_class_type(cpp_class)
82 , m_destructor(destructor)
83 , m_const_holder_destructor(const_holder_destructor)
84 , m_operator_cache(0)
86 assert(m_holder_alignment >= 1 && "internal error");
88 lua_newtable(L);
89 m_table_ref = detail::ref(L);
91 class_registry* r = class_registry::get_registry(L);
92 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
94 detail::getref(L, r->cpp_class());
95 lua_setmetatable(L, -2);
97 lua_pushvalue(L, -1); // duplicate our user data
98 m_self_ref = detail::ref(L); // pop one of them
100 m_instance_metatable = r->cpp_instance();
103 luabind::detail::class_rep::class_rep(lua_State* L, const char* name)
104 : m_type(LUABIND_INVALID_TYPE_INFO)
105 , m_holder_type(LUABIND_INVALID_TYPE_INFO)
106 , m_const_holder_type(LUABIND_INVALID_TYPE_INFO)
107 , m_extractor(0)
108 , m_const_extractor(0)
109 , m_const_converter(0)
110 , m_construct_holder(0)
111 , m_construct_const_holder(0)
112 , m_holder_size(0)
113 , m_holder_alignment(1)
114 , m_class_type(lua_class)
115 , m_destructor(0)
116 , m_const_holder_destructor(0)
117 , m_operator_cache(0)
119 #ifndef LUABIND_DONT_COPY_STRINGS
120 m_strings.push_back(detail::dup_string(name));
121 m_name = m_strings.back();
122 #else
123 m_name = name;
124 #endif
125 lua_newtable(L);
126 m_table_ref = detail::ref(L);
128 class_registry* r = class_registry::get_registry(L);
129 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
131 detail::getref(L, r->lua_class());
132 lua_setmetatable(L, -2);
133 lua_pushvalue(L, -1); // duplicate our user data
134 m_self_ref = detail::ref(L); // pop one of them
136 m_instance_metatable = r->lua_instance();
139 luabind::detail::class_rep::~class_rep()
141 #ifndef LUABIND_DONT_COPY_STRINGS
142 for (std::vector<char*>::iterator i = m_strings.begin();
143 i != m_strings.end(); ++i)
145 delete[] *i;
147 #endif
150 // leaves object on lua stack
151 std::pair<void*,void*>
152 luabind::detail::class_rep::allocate(lua_State* L) const
154 const int overlap = sizeof(object_rep)&(m_holder_alignment-1);
155 const int padding = overlap==0?0:m_holder_alignment-overlap;
156 const int size = sizeof(object_rep) + padding + m_holder_size;
158 char* mem = static_cast<char*>(lua_newuserdata(L, size));
159 char* ptr = mem + sizeof(object_rep) + padding;
161 return std::pair<void*,void*>(mem,ptr);
164 //#include <iostream>
165 // lua stack: userdata, key
166 int luabind::detail::class_rep::gettable(lua_State* L)
168 // if key is nil, return nil
169 if (lua_isnil(L, 2))
171 lua_pushnil(L);
172 return 1;
175 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
177 // we have to ignore the first argument since this may point to
178 // a method that is not present in this class (but in a subclass)
179 const char* key = lua_tostring(L, 2);
181 // special case to see if this is a null-pointer
182 if (key && !std::strcmp(key, "__ok"))
184 class_rep* crep = obj->crep();
186 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
187 : obj->ptr();
189 lua_pushboolean(L, p != 0);
190 return 1;
193 detail::getref(L, obj->crep()->table_ref());
194 lua_pushvalue(L, 2);
195 lua_gettable(L, -2);
197 if (!lua_isnil(L, -1))
199 // std::cout << "method found in lua table: " << key << "\n";
200 lua_remove(L, -2); // more table
201 return 1;
204 lua_pop(L, 2);
206 std::map<const char*, method_rep, ltstr>::iterator i = m_methods.find(key);
208 if (i != m_methods.end())
210 // the name is a method, return it
211 lua_pushlightuserdata(L, &i->second);
212 lua_pushcclosure(L, function_dispatcher, 1);
213 return 1;
216 std::map<const char*, callback, ltstr>::iterator j = m_getters.find(key);
217 if (j != m_getters.end())
219 // the name is a data member
220 return j->second.func(L, j->second.pointer_offset);
223 lua_pushnil(L);
224 return 1;
227 // called from the metamethod for __newindex
228 // the object pointer is passed on the lua stack
229 // lua stack: userdata, key, value
230 bool luabind::detail::class_rep::settable(lua_State* L)
232 // if the key is 'nil' fail
233 if (lua_isnil(L, 2)) return false;
235 // we have to ignore the first argument since this may point to
236 // a method that is not present in this class (but in a subclass)
237 const char* key = lua_tostring(L, 2);
238 std::map<const char*, callback, ltstr>::iterator j = m_setters.find(key);
239 if (j != m_setters.end())
241 // the name is a data member
242 j->second.func(L, j->second.pointer_offset);
243 return true;
246 if (m_getters.find(key) != m_getters.end())
248 // this means that we have a getter but no
249 // setter for an attribute. We will then fail
250 // because that attribute is read-only
251 return false;
254 // set the attribute to the object's table
255 getref(L, table_ref());
256 lua_pushvalue(L, 2);
257 lua_pushvalue(L, 3);
258 lua_settable(L, 4);
259 lua_pop(L, 3);
260 return true;
263 int class_rep::gettable_dispatcher(lua_State* L)
265 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
266 return obj->crep()->gettable(L);
269 // this is called as __newindex metamethod on every instance of this class
270 int luabind::detail::class_rep::settable_dispatcher(lua_State* L)
272 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
274 bool success = obj->crep()->settable(L);
276 #ifndef LUABIND_NO_ERROR_CHECKING
278 if (!success)
280 // this block is needed to make sure the std::string is destructed before
281 // lua_error() is called
282 #ifdef BOOST_MSVC
284 // msvc has a bug which deletes the string twice, that's
285 // why we have to create it on the heap
286 std::string* msg = new std::string("cannot set attribute '");
287 *msg += obj->crep()->m_name;
288 *msg += ".";
289 *msg += lua_tostring(L, -2);
290 *msg += "'";
291 lua_pushstring(L, msg->c_str());
292 delete msg;
294 #else
296 std::string msg = "cannot set attribute '";
297 msg += obj->crep()->m_name;
298 msg += ".";
299 msg += lua_tostring(L, -2);
300 msg += "'";
301 lua_pushstring(L, msg.c_str());
303 #endif
304 lua_error(L);
307 #endif
309 return 0;
313 int luabind::detail::class_rep::operator_dispatcher(lua_State* L)
315 int id = static_cast<int>(lua_tonumber(L, lua_upvalueindex(1)));
317 int operand_id = 0;
319 object_rep* operand[2];
320 for (int i = 0; i < 2; ++i)
321 operand[i] = detail::is_class_object(L, i + 1);
323 // we cannot compare the types here, we have to compare the pointers of the class_reps
324 // since all lua-classes have the same type (LUABIND_INVALID_TYPE_INFO)
325 if (operand[0] && operand[1])
326 if (operand[0]->crep() == operand[1]->crep()) operand[1] = 0;
328 std::vector<operator_callback>* overloads[2];
329 for (int i = 0; i < 2; ++i)
330 if (operand[i]) overloads[i] = &operand[i]->crep()->m_operators[id]; else overloads[i] = 0;
332 std::size_t num_overloads[2];
333 for (int i = 0; i < 2; ++i)
334 if (overloads[i]) num_overloads[i] = overloads[i]->size(); else num_overloads[i] = 0;
336 for (int i = 0; i < 2; ++i)
337 if (operand[i] && operand[i]->crep()->get_class_type() == class_rep::lua_class)
339 /* // if this is a lua class we have to
340 // look in its table to see if there's
341 // any overload of this operator
342 detail::getref(L, operand[i]->crep()->table_ref());
343 lua_pushstring(L, get_operator_name(id));
344 lua_rawget(L, -2);
345 // if we have tha operator, set num_overloads to 1
346 if (lua_isfunction(L, -1)) num_overloads[i] = 1;
347 lua_pop(L, 2);*/
349 if (operand[i]->crep()->has_operator_in_lua(L, id))
350 num_overloads[i] = 1;
353 bool ambiguous = false;
354 int match_index = -1;
355 int min_match = std::numeric_limits<int>::max();
357 #ifdef LUABIND_NO_ERROR_CHECKING
359 if (num_overloads[0] == 1 && num_overloads[1] == 0)
361 operand_id = 0;
362 match_index = 0;
364 else if (num_overloads[0] == 0 && num_overloads[1] == 1)
366 operand_id = 1;
367 match_index = 0;
369 else
372 #endif
374 int num_params = lua_gettop(L);
376 // have look at the right operand.
377 // if the right operand is a class and
378 // not the same class as this, we have to
379 // try to match it's operators too
380 for (int i = 0; i < 2; ++i)
382 if (num_overloads[i])
384 if (operand[i]->crep()->get_class_type() == class_rep::lua_class)
386 // if this is a lua class
387 // and num_overloads is > 0
388 // it means that it has implemented
389 // this operator. Set match_index to
390 // 0 to signal that this operand has
391 // an overload, but leave the min_match
392 // at int-max to mark it as a last fallback
393 operand_id = i;
394 if (match_index == -1) match_index = 0;
396 else if (find_best_match(
398 , &overloads[i]->front()
399 , overloads[i]->size()
400 , sizeof(operator_callback)
401 , ambiguous
402 , min_match
403 , match_index
404 , num_params))
406 operand_id = i;
412 #ifdef LUABIND_NO_ERROR_CHECKING
416 #else
418 if (match_index == -1)
420 // this block is needed to make sure the std::string is destructed before
421 // lua_error() is called
423 std::string msg = "no operator ";
424 msg += get_operator_symbol(id);
425 msg += " matched the arguments (";
426 msg += stack_content_by_name(L, 1);
427 msg += ")\ncandidates are:\n";
429 for (int i = 0; i < 2; ++i)
431 if (overloads[i])
433 msg += get_overload_signatures(
435 , overloads[i]->begin()
436 , overloads[i]->end()
437 , get_operator_symbol(id));
439 else
441 // if num_overloads is > 0 it would mean that this is
442 // a lua class with this operator overloaded. And if
443 // that's the case, it should always match (and if an
444 // operator matches, we never come here).
445 assert(num_overloads[i] == 0 && "internal error");
449 lua_pushstring(L, msg.c_str());
451 lua_error(L);
453 else if (ambiguous)
455 // this block is needed to make sure the std::string is destructed before
456 // lua_error() is called
458 std::string msg = "call of overloaded operator ";
459 msg += get_operator_symbol(id);
460 msg += " (";
461 msg += stack_content_by_name(L, 1);
462 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
464 std::vector<const overload_rep_base*> candidates;
465 if (overloads[0])
466 find_exact_match(L, &overloads[0]->front(), overloads[0]->size(), sizeof(operator_callback), min_match, num_params, candidates);
468 if (overloads[1])
469 find_exact_match(L, &overloads[1]->front(), overloads[1]->size(), sizeof(operator_callback), min_match, num_params, candidates);
471 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), get_operator_symbol(id));
473 lua_pushstring(L, msg.c_str());
475 lua_error(L);
478 #endif
480 if (operand[operand_id]->crep()->get_class_type() == class_rep::lua_class)
482 detail::getref(L, operand[operand_id]->crep()->table_ref());
483 lua_pushstring(L, get_operator_name(id));
484 lua_rawget(L, -2);
485 lua_insert(L, -4); // move the function to the bottom
486 lua_pop(L, 1); // remove the table
487 lua_call(L, 2, 1);
488 return 1;
490 else
492 return (*overloads[operand_id])[match_index].call(L);
496 // this is called as metamethod __call on the class_rep.
497 int luabind::detail::class_rep::constructor_dispatcher(lua_State* L)
499 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
500 construct_rep* rep = &crep->m_constructor;
502 bool ambiguous = false;
503 int match_index = -1;
504 int min_match = std::numeric_limits<int>::max();
505 bool found;
507 #ifdef LUABIND_NO_ERROR_CHECKING
509 if (rep->overloads.size() == 1)
511 match_index = 0;
513 else
516 #endif
518 int num_params = lua_gettop(L) - 1;
519 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
521 #ifdef LUABIND_NO_ERROR_CHECKING
524 #else
526 if (!found)
528 // this block is needed to make sure the std::string is destructed before
529 // lua_error() is called
531 std::string msg = "no constructor of '";
532 msg += crep->name();
533 msg += "' matched the arguments (";
534 msg += stack_content_by_name(L, 2);
535 msg += ")\n candidates are:\n";
537 msg += get_overload_signatures(L, rep->overloads.begin(), rep->overloads.end(), crep->name());
539 lua_pushstring(L, msg.c_str());
541 lua_error(L);
543 else if (ambiguous)
545 // this block is needed to make sure the std::string is destructed before
546 // lua_error() is called
548 std::string msg = "call of overloaded constructor '";
549 msg += crep->m_name;
550 msg += "(";
551 msg += stack_content_by_name(L, 2);
552 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
554 std::vector<const overload_rep_base*> candidates;
555 find_exact_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), min_match, num_params, candidates);
556 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), crep->name());
558 lua_pushstring(L, msg.c_str());
560 lua_error(L);
563 #endif
565 #ifndef LUABIND_NO_EXCEPTIONS
570 #endif
572 void* object_ptr = rep->overloads[match_index].construct(L);
574 void* obj_rep;
575 void* held;
577 boost::tie(obj_rep,held) = crep->allocate(L);
579 if (crep->has_holder())
581 crep->m_construct_holder(held, object_ptr);
582 object_ptr = held;
584 new(obj_rep) object_rep(object_ptr, crep, object_rep::owner, crep->destructor());
586 detail::getref(L, crep->m_instance_metatable);
587 lua_setmetatable(L, -2);
588 return 1;
590 #ifndef LUABIND_NO_EXCEPTIONS
594 catch(const std::exception& e)
596 lua_pushstring(L, e.what());
598 catch(const char* s)
600 lua_pushstring(L, s);
602 catch(...)
605 std::string msg = crep->name();
606 msg += "() threw an exception";
607 lua_pushstring(L, msg.c_str());
611 // we can only reach this line if an exception was thrown
612 lua_error(L);
613 return 0; // will never be reached
615 #endif
619 // the functions dispatcher assumes the following:
620 // there is one upvalue that points to the method_rep that this dispatcher is to call
621 // the first parameter on the lua stack is an object_rep that points to the object the
622 // call is being made on
623 int luabind::detail::class_rep::function_dispatcher(lua_State* L)
625 method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
626 object_rep* obj = reinterpret_cast<object_rep*>(lua_touserdata(L, 1));
628 #ifndef LUABIND_NO_ERROR_CHECKING
630 if (is_class_object(L, 1) == 0)
633 std::string msg = "No self reference given as first parameter to member function '";
634 msg += rep->crep->name();
635 msg += ":";
636 msg += rep->name;
637 msg += "'. Have you used '.' instead of ':'?";
639 lua_pushstring(L, msg.c_str());
641 lua_error(L);
644 int p;
645 if (implicit_cast(obj->crep(), rep->crep->type(), p) < 0)
648 std::string msg = "invalid self reference given to '";
649 msg += rep->crep->name();
650 msg += ":";
651 msg += rep->name;
652 msg += "'";
653 lua_pushstring(L, msg.c_str());
655 lua_error(L);
658 #endif
660 bool ambiguous = false;
661 int match_index = -1;
662 int min_match = std::numeric_limits<int>::max();
663 bool found;
665 #ifdef LUABIND_NO_ERROR_CHECKING
666 if (rep->overloads().size() == 1)
668 match_index = 0;
670 else
672 #endif
674 int num_params = lua_gettop(L) - 1;
675 found = find_best_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), ambiguous, min_match, match_index, num_params);
677 #ifdef LUABIND_NO_ERROR_CHECKING
681 #else
683 if (!found)
686 std::string msg = "no overload of '";
687 msg += rep->crep->name();
688 msg += ":";
689 msg += rep->name;
690 msg += "' matched the arguments (";
691 msg += stack_content_by_name(L, 2);
692 msg += ")\ncandidates are:\n";
694 std::string function_name;
695 function_name += rep->crep->name();
696 function_name += ":";
697 function_name += rep->name;
699 msg += get_overload_signatures(L, rep->overloads().begin(), rep->overloads().end(), function_name);
701 lua_pushstring(L, msg.c_str());
703 lua_error(L);
705 else if (ambiguous)
708 std::string msg = "call of overloaded '";
709 msg += rep->crep->name();
710 msg += ":";
711 msg += rep->name;
712 msg += "(";
713 msg += stack_content_by_name(L, 2);
714 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
716 std::vector<const overload_rep_base*> candidates;
717 find_exact_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), min_match, num_params, candidates);
719 std::string function_name;
720 function_name += rep->crep->name();
721 function_name += ":";
722 function_name += rep->name;
724 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), function_name);
726 lua_pushstring(L, msg.c_str());
728 lua_error(L);
731 #endif
733 #ifndef LUABIND_NO_EXCEPTIONS
738 #endif
740 const overload_rep& o = rep->overloads()[match_index];
741 return o.call(L, *obj);
743 #ifndef LUABIND_NO_EXCEPTIONS
746 catch(const std::exception& e)
748 lua_pushstring(L, e.what());
750 catch (const char* s)
752 lua_pushstring(L, s);
754 catch(...)
756 std::string msg = rep->crep->name();
757 msg += ":";
758 msg += rep->name;
759 msg += "() threw an exception";
760 lua_pushstring(L, msg.c_str());
762 // we can only reach this line if an exception was thrown
763 lua_error(L);
764 return 0; // will never be reached
766 #endif
770 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo)
772 // If you hit this assert you are deriving from a type that is not registered
773 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
774 // Please note that if you don't need to have access to the base class or the
775 // conversion from the derived class to the base class, you don't need
776 // to tell luabind that it derives.
777 assert(binfo.base && "You cannot derive from an unregistered type");
779 class_rep* bcrep = binfo.base;
781 // import all functions from the base
782 for (std::map<const char*, method_rep, ltstr>::const_iterator i = bcrep->m_methods.begin();
783 i != bcrep->m_methods.end(); ++i)
785 // If we would assume that our base class will not be garbage collected until
786 // this class is collected, we wouldn't had to copy these strings.
787 #ifndef LUABIND_DONT_COPY_STRINGS
788 m_strings.push_back(dup_string(i->first));
789 method_rep& m = m_methods[m_strings.back()];
790 #else
791 method_rep& m = m_methods[i->first];
792 #endif
793 m.name = i->first;
794 m.crep = this;
796 for (std::vector<overload_rep>::const_iterator j = i->second.overloads().begin();
797 j != i->second.overloads().end(); ++j)
799 overload_rep o = *j;
800 o.add_offset(binfo.pointer_offset);
801 m.add_overload(o);
805 // import all getters from the base
806 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_getters.begin();
807 i != bcrep->m_getters.end(); ++i)
809 #ifndef LUABIND_DONT_COPY_STRINGS
810 m_strings.push_back(dup_string(i->first));
811 callback& m = m_getters[m_strings.back()];
812 #else
813 callback& m = m_getters[i->first];
814 #endif
815 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
816 m.func = i->second.func;
819 // import all setters from the base
820 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_setters.begin();
821 i != bcrep->m_setters.end(); ++i)
823 #ifndef LUABIND_DONT_COPY_STRINGS
824 // TODO: optimize this by not copying the string if it already exists in m_setters.
825 // This goes for m_getters, m_static_constants and m_functions too. Both here
826 // in add_base() and in the add_function(), add_getter() ... functions.
827 m_strings.push_back(dup_string(i->first));
828 callback& m = m_setters[m_strings.back()];
829 #else
830 callback& m = m_setters[i->first];
831 #endif
832 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
833 m.func = i->second.func;
836 // import all static constants
837 for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin();
838 i != bcrep->m_static_constants.end(); ++i)
840 #ifndef LUABIND_DONT_COPY_STRINGS
841 m_strings.push_back(dup_string(i->first));
842 int& v = m_static_constants[m_strings.back()];
843 #else
844 int& v = m_static_constants[i->first];
845 #endif
846 v = i->second;
849 // import all operators
850 for (int i = 0; i < number_of_operators; ++i)
852 for (std::vector<operator_callback>::const_iterator j = bcrep->m_operators[i].begin();
853 j != bcrep->m_operators[i].end(); ++j)
854 m_operators[i].push_back(*j);
857 // also, save the baseclass info to be used for typecasts
858 m_bases.push_back(binfo);
861 void luabind::detail::class_rep::add_function(const char* name, const overload_rep& o)
864 #ifdef LUABIND_DONT_COPY_STRINGS
865 detail::method_rep& method = m_methods[name];
866 method.name = name;
867 #else
868 m_strings.push_back(dup_string(name));
869 detail::method_rep& method = m_methods[m_strings.back()];
870 method.name = m_strings.back();
871 #endif
873 method.add_overload(o);
874 method.crep = this;
877 void luabind::detail::class_rep::add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
879 callback c;
880 c.func = g;
881 c.pointer_offset = 0;
882 #ifndef LUABIND_DONT_COPY_STRINGS
883 m_strings.push_back(dup_string(name));
884 m_getters[m_strings.back()] = c;
885 #else
886 m_getters[name] = c;
887 #endif
890 void luabind::detail::class_rep::add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
892 callback c;
893 c.func = s;
894 c.pointer_offset = 0;
895 #ifndef LUABIND_DONT_COPY_STRINGS
896 m_strings.push_back(dup_string(name));
897 m_setters[m_strings.back()] = c;
898 #else
899 m_setters[name] = c;
900 #endif
903 #ifndef LUABIND_NO_ERROR_CHECKING
904 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)
905 #else
906 void luabind::detail::class_rep::add_operator(lua_State*, int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
907 #endif
909 operator_callback o;
910 o.set_fun(func);
911 o.set_match_fun(matcher);
912 o.set_arity(arity);
914 #ifndef LUABIND_NO_ERROR_CHECKING
916 o.set_sig_fun(sig);
918 #endif
919 m_operators[op_id].push_back(o);
922 void luabind::detail::class_rep::add_static_constant(const char* name, int val)
924 #ifndef LUABIND_DONT_COPY_STRINGS
925 m_strings.push_back(dup_string(name));
926 m_static_constants[m_strings.back()] = val;
927 #else
928 m_static_constants[name] = val;
929 #endif
932 int luabind::detail::class_rep::super_callback(lua_State* L)
934 int args = lua_gettop(L);
936 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, lua_upvalueindex(2)));
937 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
938 class_rep* base = crep->bases()[0].base;
940 if (base->get_class_type() == class_rep::lua_class)
942 if (base->bases().empty())
944 obj->set_flags(obj->flags() & ~object_rep::call_super);
946 lua_pushstring(L, "super");
947 lua_pushnil(L);
948 lua_settable(L, LUA_GLOBALSINDEX);
950 else
952 lua_pushstring(L, "super");
953 lua_pushlightuserdata(L, base);
954 lua_pushvalue(L, lua_upvalueindex(2));
955 lua_pushcclosure(L, super_callback, 2);
956 lua_settable(L, LUA_GLOBALSINDEX);
959 detail::getref(L, base->table_ref());
960 lua_pushstring(L, "__init");
961 lua_gettable(L, -2);
962 lua_insert(L, 1);
963 lua_pop(L, 1);
965 lua_pushvalue(L, lua_upvalueindex(2));
966 lua_insert(L, 2);
968 lua_call(L, args + 1, 0);
970 // TODO: instead of clearing the global variable "super"
971 // store it temporarily in the registry. maybe we should
972 // have some kind of warning if the super global is used?
973 lua_pushstring(L, "super");
974 lua_pushnil(L);
975 lua_settable(L, LUA_GLOBALSINDEX);
977 else
979 obj->set_flags(obj->flags() & ~object_rep::call_super);
981 // we need to push some garbage at index 1 to make the construction work
982 lua_pushboolean(L, 1);
983 lua_insert(L, 1);
985 construct_rep* rep = &base->m_constructor;
987 bool ambiguous = false;
988 int match_index = -1;
989 int min_match = std::numeric_limits<int>::max();
990 bool found;
992 #ifdef LUABIND_NO_ERROR_CHECKING
994 if (rep->overloads.size() == 1)
996 match_index = 0;
998 else
1001 #endif
1003 int num_params = lua_gettop(L) - 1;
1004 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
1006 #ifdef LUABIND_NO_ERROR_CHECKING
1010 #else
1012 if (!found)
1015 std::string msg = "no constructor of '";
1016 msg += base->m_name;
1017 msg += "' matched the arguments (";
1018 msg += stack_content_by_name(L, 2);
1019 msg += ")";
1020 lua_pushstring(L, msg.c_str());
1022 lua_error(L);
1024 else if (ambiguous)
1027 std::string msg = "call of overloaded constructor '";
1028 msg += base->m_name;
1029 msg += "(";
1030 msg += stack_content_by_name(L, 2);
1031 msg += ")' is ambiguous";
1032 lua_pushstring(L, msg.c_str());
1034 lua_error(L);
1037 // TODO: should this be a warning or something?
1039 // since the derived class is a lua class
1040 // it may have reimplemented virtual functions
1041 // therefore, we have to instantiate the Basewrapper
1042 // if there is no basewrapper, throw a run-time error
1043 if (!rep->overloads[match_index].has_wrapped_construct())
1046 std::string msg = "Cannot derive from C++ class '";
1047 msg += base->name();
1048 msg += "'. It does not have a wrapped type";
1049 lua_pushstring(L, msg.c_str());
1051 lua_error(L);
1054 #endif
1056 #ifndef LUABIND_NO_EXCEPTIONS
1061 #endif
1062 void* storage_ptr = obj->ptr();
1064 if (!rep->overloads[match_index].has_wrapped_construct())
1066 // if the type doesn't have a wrapped type, use the ordinary constructor
1067 void* instance = rep->overloads[match_index].construct(L);
1069 if (crep->has_holder())
1071 crep->m_construct_holder(storage_ptr, instance);
1073 else
1075 obj->set_object(instance);
1078 else
1080 // get reference to lua object
1081 lua_pushvalue(L, lua_upvalueindex(2));
1082 int ref = detail::ref(L);
1084 void* instance = rep->overloads[match_index].construct_wrapped(L, ref);
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 std::exception& e)
1107 lua_pushstring(L, e.what());
1109 catch(const char* s)
1111 lua_pushstring(L, s);
1113 catch(...)
1115 std::string msg = base->m_name;
1116 msg += "() threw an exception";
1117 lua_pushstring(L, msg.c_str());
1119 // can only be reached if an exception was thrown
1120 lua_error(L);
1121 #endif
1124 return 0;
1130 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L)
1132 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1133 detail::getref(L, crep->m_table_ref);
1134 lua_replace(L, 1);
1135 lua_rawset(L, -3);
1137 crep->m_operator_cache = 0; // invalidate cache
1139 return 0;
1142 int luabind::detail::class_rep::construct_lua_class_callback(lua_State* L)
1144 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1146 int args = lua_gettop(L);
1148 // lua stack: crep <arguments>
1150 lua_newtable(L);
1151 int ref = detail::ref(L);
1153 bool has_bases = !crep->bases().empty();
1155 if (has_bases)
1157 lua_pushstring(L, "super");
1158 lua_pushvalue(L, 1); // crep
1161 // lua stack: crep <arguments> "super" crep
1162 // or
1163 // lua stack: crep <arguments>
1165 // if we have a baseclass we set the flag to say that the super has not yet been called
1166 // we will use this flag later to check that it actually was called from __init()
1167 int flags = object_rep::lua_class | object_rep::owner | (has_bases ? object_rep::call_super : 0);
1169 // void* obj_ptr = lua_newuserdata(L, sizeof(object_rep));
1170 void* obj_ptr;
1171 void* held_storage;
1173 boost::tie(obj_ptr, held_storage) = crep->allocate(L);
1174 (new(obj_ptr) object_rep(crep, flags, ref))->set_object(held_storage);
1176 detail::getref(L, crep->metatable_ref());
1177 lua_setmetatable(L, -2);
1179 // lua stack: crep <arguments> "super" crep obj_ptr
1180 // or
1181 // lua stack: crep <arguments> obj_ptr
1183 if (has_bases) lua_pushvalue(L, -1); // obj_ptr
1184 lua_replace(L, 1); // obj_ptr
1186 // lua stack: obj_ptr <arguments> "super" crep obj_ptr
1187 // or
1188 // lua stack: obj_ptr <arguments>
1190 if (has_bases)
1192 lua_pushcclosure(L, super_callback, 2);
1193 // lua stack: crep <arguments> "super" function
1194 lua_settable(L, LUA_GLOBALSINDEX);
1197 // lua stack: crep <arguments>
1199 lua_pushvalue(L, 1);
1200 lua_insert(L, 1);
1202 detail::getref(L, crep->table_ref());
1203 lua_pushstring(L, "__init");
1204 lua_gettable(L, -2);
1206 #ifndef LUABIND_NO_ERROR_CHECKING
1208 // TODO: should this be a run-time error?
1209 // maybe the default behavior should be to just call
1210 // the base calss' constructor. We should register
1211 // the super callback funktion as __init
1212 if (!lua_isfunction(L, -1))
1215 std::string msg = crep->name();
1216 msg += ":__init is not defined";
1217 lua_pushstring(L, msg.c_str());
1219 lua_error(L);
1222 #endif
1224 lua_insert(L, 2); // function first on stack
1225 lua_pop(L, 1);
1226 // TODO: lua_call may invoke longjump! make sure we don't have any memory leaks!
1227 // we don't have any stack objects here
1228 lua_call(L, args, 0);
1230 #ifndef LUABIND_NO_ERROR_CHECKING
1232 object_rep* obj = static_cast<object_rep*>(obj_ptr);
1233 if (obj->flags() & object_rep::call_super)
1235 lua_pushstring(L, "derived class must call super on base");
1236 lua_error(L);
1239 #endif
1241 return 1;
1244 // called from the metamethod for __index
1245 // obj is the object pointer
1246 int luabind::detail::class_rep::lua_class_gettable(lua_State* L)
1248 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1249 class_rep* crep = obj->crep();
1251 #ifndef LUABIND_NO_ERROR_CHECKING
1253 if (obj->flags() & object_rep::call_super)
1255 lua_pushstring(L, "derived class must call super on base");
1256 lua_error(L);
1259 #endif
1261 // we have to ignore the first argument since this may point to
1262 // a method that is not present in this class (but in a subclass)
1263 const char* key = lua_tostring(L, 2);
1265 if (key && !std::strcmp(key, "__ok"))
1267 class_rep* crep = obj->crep();
1269 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
1270 : obj->ptr();
1272 lua_pushboolean(L, p != 0);
1273 return 1;
1276 detail::getref(L, obj->lua_table_ref());
1277 lua_pushvalue(L, 2);
1278 lua_gettable(L, -2);
1280 if (!lua_isnil(L, -1))
1282 lua_remove(L, -2); // remove table
1283 return 1;
1286 lua_pop(L, 2);
1288 detail::getref(L, crep->table_ref());
1289 lua_pushvalue(L, 2);
1290 lua_gettable(L, -2);
1292 if (!lua_isnil(L, -1))
1294 lua_remove(L, -2); // more table
1295 return 1;
1298 lua_pop(L, 2);
1300 if (lua_isnil(L, 2))
1302 lua_pushnil(L);
1303 return 1;
1306 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1307 if (i != crep->m_methods.end())
1309 // the name is a method, return it
1310 lua_pushlightuserdata(L, &i->second);
1311 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1312 return 1;
1315 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_getters.find(key);
1316 if (j != crep->m_getters.end())
1318 // the name is a data member
1319 return j->second.func(L, j->second.pointer_offset);
1322 lua_pushnil(L);
1323 return 1;
1326 // called from the metamethod for __newindex
1327 // obj is the object pointer
1328 int luabind::detail::class_rep::lua_class_settable(lua_State* L)
1330 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1331 class_rep* crep = obj->crep();
1333 #ifndef LUABIND_NO_ERROR_CHECKING
1335 if (obj->flags() & object_rep::call_super)
1337 // this block makes sure the std::string is destructed
1338 // before lua_error is called
1340 std::string msg = "derived class '";
1341 msg += crep->name();
1342 msg += "'must call super on base";
1343 lua_pushstring(L, msg.c_str());
1345 lua_error(L);
1348 #endif
1350 // we have to ignore the first argument since this may point to
1351 // a method that is not present in this class (but in a subclass)
1352 const char* key = lua_tostring(L, 2);
1353 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_setters.find(key);
1355 if (j == crep->m_setters.end())
1357 std::map<const char*, class_rep::callback, ltstr>::iterator k = crep->m_getters.find(key);
1359 #ifndef LUABIND_NO_ERROR_CHECKING
1361 if (k != crep->m_getters.end())
1364 std::string msg = "cannot set property '";
1365 msg += crep->name();
1366 msg += ".";
1367 msg += key;
1368 msg += "', because it's read only";
1369 lua_pushstring(L, msg.c_str());
1371 lua_error(L);
1374 #endif
1376 detail::getref(L, obj->lua_table_ref());
1377 lua_replace(L, 1);
1378 lua_settable(L, 1);
1380 else
1382 // the name is a data member
1383 j->second.func(L, j->second.pointer_offset);
1386 return 0;
1389 int luabind::detail::class_rep::static_class_gettable(lua_State* L)
1391 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1393 // this has changed! c++ classes now also store their methods in the table
1394 // if (crep->get_class_type() == class_rep::lua_class)
1396 detail::getref(L, crep->m_table_ref);
1397 lua_pushvalue(L, 2);
1398 lua_gettable(L, -2);
1399 if (!lua_isnil(L, -1)) return 1;
1400 else lua_pop(L, 2);
1403 const char* key = lua_tostring(L, 2);
1405 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1406 if (i != crep->m_methods.end())
1408 // the name is a method, return it
1409 lua_pushlightuserdata(L, &i->second);
1410 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1411 return 1;
1414 std::map<const char*, int, ltstr>::const_iterator j = crep->m_static_constants.find(key);
1416 if (j != crep->m_static_constants.end())
1418 lua_pushnumber(L, j->second);
1419 return 1;
1422 #ifndef LUABIND_NO_ERROR_CHECKING
1425 std::string msg = "no static '";
1426 msg += key;
1427 msg += "' in class '";
1428 msg += crep->name();
1429 msg += "'";
1430 lua_pushstring(L, msg.c_str());
1432 lua_error(L);
1434 #endif
1436 lua_pushnil(L);
1438 return 1;
1441 bool luabind::detail::is_class_rep(lua_State* L, int index)
1443 if (lua_getmetatable(L, index) == 0) return false;
1445 lua_pushstring(L, "__luabind_classrep");
1446 lua_gettable(L, -2);
1447 if (lua_toboolean(L, -1))
1449 lua_pop(L, 2);
1450 return true;
1453 lua_pop(L, 2);
1454 return false;
1457 void luabind::detail::finalize(lua_State* L, class_rep* crep)
1459 if (crep->get_class_type() != class_rep::lua_class) return;
1461 // lua_pushvalue(L, -1); // copy the object ref
1462 detail::getref(L, crep->table_ref());
1463 lua_pushstring(L, "__finalize");
1464 lua_gettable(L, -2);
1465 lua_remove(L, -2);
1467 if (lua_isnil(L, -1))
1469 lua_pop(L, 1);
1471 else
1473 lua_pushvalue(L, -2);
1474 lua_call(L, 1, 0);
1477 for (std::vector<class_rep::base_info>::const_iterator
1478 i = crep->bases().begin(); i != crep->bases().end(); ++i)
1480 if (i->base) finalize(L, i->base);
1484 void* luabind::detail::class_rep::convert_to(LUABIND_TYPE_INFO target_type, const object_rep* obj, void* target_memory) const
1486 // TODO: since this is a member function, we don't have to use the accesor functions for
1487 // the types and the extractor
1489 int steps = 0;
1490 int offset = 0;
1491 if (!(LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), target_type))
1492 && !(LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), target_type)))
1494 steps = implicit_cast(this, target_type, offset);
1497 // should never be called with a type that can't be cast
1498 assert((steps >= 0) && "internal error, please report");
1500 if (LUABIND_TYPE_INFO_EQUAL(target_type, holder_type()))
1502 // if the type we are trying to convert to is the holder_type
1503 // it means that his crep has a holder_type (since it would have
1504 // been invalid otherwise, and T cannot be invalid). It also means
1505 // that we need no conversion, since the holder_type is what the
1506 // object points to.
1507 return obj->ptr();
1510 if (LUABIND_TYPE_INFO_EQUAL(target_type, const_holder_type()))
1512 if (obj->flags() & object_rep::constant)
1514 // we are holding a constant
1515 return obj->ptr();
1517 else
1519 // we are holding a non-constant, we need to convert it
1520 // to a const_holder.
1521 m_const_converter(obj->ptr(), target_memory);
1522 return target_memory;
1526 void* raw_pointer;
1528 if (has_holder())
1530 // this means that we have a holder type where the
1531 // raw-pointer needs to be extracted
1532 raw_pointer = extractor()(obj->ptr());
1534 else
1536 raw_pointer = obj->ptr();
1539 return static_cast<char*>(raw_pointer) + offset;
1542 void luabind::detail::class_rep::cache_operators(lua_State* L)
1544 m_operator_cache = 0x1;
1546 for (int i = 0; i < number_of_operators; ++i)
1548 getref(L, table_ref());
1549 lua_pushstring(L, get_operator_name(i));
1550 lua_rawget(L, -2);
1552 if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1);
1554 lua_pop(L, 2);
1558 bool luabind::detail::class_rep::has_operator_in_lua(lua_State* L, int id)
1560 if ((m_operator_cache & 0x1) == 0)
1561 cache_operators(L);
1563 const int mask = 1 << (id + 1);
1565 return (m_operator_cache & mask) != 0;
1568 void luabind::detail::class_rep::add_method(lua_State* L, const char* name, detail::method_rep& m)
1570 detail::getref(L, table_ref());
1571 lua_pushstring(L, name);
1572 lua_gettable(L, -2);
1574 if (lua_isnil(L, -1) || !lua_iscfunction(L, -1))
1576 lua_pop(L, 1);
1577 lua_pushstring(L, name);
1578 lua_pushlightuserdata(L, const_cast<void*>((const void*)&m));
1579 lua_pushcclosure(L, function_dispatcher, 1);
1580 lua_settable(L, -3);
1581 lua_pop(L, 1);
1583 else
1585 lua_getupvalue(L, -1, 1);
1586 method_rep* inherited = static_cast<method_rep*>(lua_touserdata(L, -1));
1588 for (std::vector<overload_rep>::const_iterator i = inherited->overloads().begin();
1589 i != inherited->overloads().end(); ++i)
1591 m.add_overload(*i);
1594 detail::getref(L, table_ref());
1595 lua_pushstring(L, name);
1596 lua_pushlightuserdata(L, const_cast<void*>((const void*)&m));
1597 lua_pushcclosure(L, function_dispatcher, 1);
1598 lua_settable(L, -3);
1599 lua_pop(L, 4);
1603 const class_rep::property_map& luabind::detail::class_rep::properties() const
1605 return m_getters;