*** empty log message ***
[luabind.git] / src / class_rep.cpp
blobe5c4c5e9e34972d7b0b6de331571a8fcb6e2c872
1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
23 #include <luabind/lua_include.hpp>
25 #include <luabind/luabind.hpp>
26 #include <utility>
28 using namespace luabind::detail;
31 #ifndef LUABIND_NO_ERROR_CHECKING
33 std::string luabind::detail::get_overload_signatures_candidates(
34 lua_State* L
35 , std::vector<const overload_rep_base*>::iterator start
36 , std::vector<const overload_rep_base*>::iterator end
37 , std::string name)
39 std::string s;
40 for (; start != end; ++start)
42 s += name;
43 (*start)->get_signature(L, s);
44 s += "\n";
46 return s;
49 #endif
52 luabind::detail::class_rep::class_rep(LUABIND_TYPE_INFO type
53 , const char* name
54 , lua_State* L
55 , void(*destructor)(void*)
56 , void(*const_holder_destructor)(void*)
57 , LUABIND_TYPE_INFO holder_type
58 , LUABIND_TYPE_INFO const_holder_type
59 , void*(*extractor)(void*)
60 , const void*(*const_extractor)(void*)
61 , void(*const_converter)(void*,void*)
62 , void(*construct_holder)(void*,void*)
63 , void(*construct_const_holder)(void*,void*)
64 , void(*default_construct_holder)(void*)
65 , void(*default_construct_const_holder)(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_default_construct_holder(default_construct_holder)
78 , m_default_construct_const_holder(default_construct_const_holder)
79 , m_holder_size(holder_size)
80 , m_holder_alignment(holder_alignment)
81 , m_name(name)
82 , m_table_ref(LUA_NOREF)
83 , m_class_type(cpp_class)
84 , m_destructor(destructor)
85 , m_const_holder_destructor(const_holder_destructor)
86 , m_operator_cache(0)
88 assert(m_holder_alignment >= 1 && "internal error");
90 lua_newtable(L);
91 m_table_ref = detail::ref(L);
93 class_registry* r = class_registry::get_registry(L);
94 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
96 detail::getref(L, r->cpp_class());
97 lua_setmetatable(L, -2);
99 lua_pushvalue(L, -1); // duplicate our user data
100 m_self_ref = detail::ref(L); // pop one of them
102 m_instance_metatable = r->cpp_instance();
105 luabind::detail::class_rep::class_rep(lua_State* L, const char* name)
106 : m_type(LUABIND_INVALID_TYPE_INFO)
107 , m_holder_type(LUABIND_INVALID_TYPE_INFO)
108 , m_const_holder_type(LUABIND_INVALID_TYPE_INFO)
109 , m_extractor(0)
110 , m_const_extractor(0)
111 , m_const_converter(0)
112 , m_construct_holder(0)
113 , m_construct_const_holder(0)
114 , m_default_construct_holder(0)
115 , m_default_construct_const_holder(0)
116 , m_holder_size(0)
117 , m_holder_alignment(1)
118 , m_class_type(lua_class)
119 , m_destructor(0)
120 , m_const_holder_destructor(0)
121 , m_operator_cache(0)
123 m_name = name;
124 lua_newtable(L);
125 m_table_ref = detail::ref(L);
127 class_registry* r = class_registry::get_registry(L);
128 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
130 detail::getref(L, r->lua_class());
131 lua_setmetatable(L, -2);
132 lua_pushvalue(L, -1); // duplicate our user data
133 m_self_ref = detail::ref(L); // pop one of them
135 m_instance_metatable = r->lua_instance();
138 luabind::detail::class_rep::~class_rep()
142 // leaves object on lua stack
143 std::pair<void*,void*>
144 luabind::detail::class_rep::allocate(lua_State* L) const
146 const int overlap = sizeof(object_rep)&(m_holder_alignment-1);
147 const int padding = overlap==0?0:m_holder_alignment-overlap;
148 const int size = sizeof(object_rep) + padding + m_holder_size;
150 char* mem = static_cast<char*>(lua_newuserdata(L, size));
151 char* ptr = mem + sizeof(object_rep) + padding;
153 return std::pair<void*,void*>(mem,ptr);
156 //#include <iostream>
157 // lua stack: userdata, key
158 int luabind::detail::class_rep::gettable(lua_State* L)
160 // if key is nil, return nil
161 if (lua_isnil(L, 2))
163 lua_pushnil(L);
164 return 1;
167 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
169 // we have to ignore the first argument since this may point to
170 // a method that is not present in this class (but in a subclass)
171 const char* key = lua_tostring(L, 2);
173 #ifndef LUABIND_NO_ERROR_CHECKING
175 if (std::strlen(key) != lua_strlen(L, 2))
178 std::string msg("luabind does not support "
179 "member names with extra nulls:\n");
180 msg += std::string(lua_tostring(L, 2), lua_strlen(L, 2));
181 lua_pushstring(L, msg.c_str());
183 lua_error(L);
186 #endif
188 // special case to see if this is a null-pointer
189 if (key && !std::strcmp(key, "__ok"))
191 class_rep* crep = obj->crep();
193 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
194 : obj->ptr();
196 lua_pushboolean(L, p != 0);
197 return 1;
200 detail::getref(L, obj->crep()->table_ref());
201 lua_pushvalue(L, 2);
202 lua_gettable(L, -2);
204 if (!lua_isnil(L, -1))
206 // std::cout << "method found in lua table: " << key << "\n";
207 lua_remove(L, -2); // more table
208 return 1;
211 lua_pop(L, 2);
213 std::map<const char*, method_rep, ltstr>::iterator i = m_methods.find(key);
215 if (i != m_methods.end())
217 // the name is a method, return it
218 lua_pushlightuserdata(L, &i->second);
219 lua_pushcclosure(L, function_dispatcher, 1);
220 return 1;
223 std::map<const char*, callback, ltstr>::iterator j = m_getters.find(key);
224 if (j != m_getters.end())
226 // the name is a data member
227 return j->second.func(L, j->second.pointer_offset);
230 lua_pushnil(L);
231 return 1;
234 // called from the metamethod for __newindex
235 // the object pointer is passed on the lua stack
236 // lua stack: userdata, key, value
237 bool luabind::detail::class_rep::settable(lua_State* L)
239 // if the key is 'nil' fail
240 if (lua_isnil(L, 2)) return false;
242 // we have to ignore the first argument since this may point to
243 // a method that is not present in this class (but in a subclass)
245 const char* key = lua_tostring(L, 2);
247 if (std::strlen(key) == lua_strlen(L, 2))
249 std::map<const char*, callback, ltstr>::iterator j = m_setters.find(key);
250 if (j != m_setters.end())
252 // the name is a data member
253 #ifndef LUABIND_NO_ERROR_CHECKING
254 if (j->second.match(L, 3) < 0)
256 std::string msg("the attribute '");
257 msg += m_name;
258 msg += ".";
259 msg += key;
260 msg += "' is of type: ";
261 j->second.sig(L, msg);
262 msg += "\nand does not match: (";
263 msg += stack_content_by_name(L, 3);
264 msg += ")";
265 lua_pushstring(L, msg.c_str());
266 return false;
268 #endif
269 j->second.func(L, j->second.pointer_offset);
270 return true;
273 if (m_getters.find(key) != m_getters.end())
275 // this means that we have a getter but no
276 // setter for an attribute. We will then fail
277 // because that attribute is read-only
278 std::string msg("the attribute '");
279 msg += m_name;
280 msg += ".";
281 msg += key;
282 msg += "' is read only";
283 lua_pushstring(L, msg.c_str());
284 return false;
288 // set the attribute to the object's table
289 getref(L, table_ref());
290 lua_pushvalue(L, 2);
291 lua_pushvalue(L, 3);
292 lua_settable(L, 4);
293 lua_pop(L, 3);
294 return true;
297 int class_rep::gettable_dispatcher(lua_State* L)
299 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
300 return obj->crep()->gettable(L);
303 // this is called as __newindex metamethod on every instance of this class
304 int luabind::detail::class_rep::settable_dispatcher(lua_State* L)
306 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
308 bool success = obj->crep()->settable(L);
310 #ifndef LUABIND_NO_ERROR_CHECKING
312 if (!success)
314 // class_rep::settable() will leave
315 // error message on the stack in case
316 // of failure
317 lua_error(L);
320 #endif
322 return 0;
326 int luabind::detail::class_rep::operator_dispatcher(lua_State* L)
328 int id = static_cast<int>(lua_tonumber(L, lua_upvalueindex(1)));
330 int operand_id = 0;
332 object_rep* operand[2];
333 for (int i = 0; i < 2; ++i)
334 operand[i] = detail::is_class_object(L, i + 1);
336 // we cannot compare the types here, we have to compare the pointers of the class_reps
337 // since all lua-classes have the same type (LUABIND_INVALID_TYPE_INFO)
338 if (operand[0] && operand[1])
339 if (operand[0]->crep() == operand[1]->crep()) operand[1] = 0;
341 std::vector<operator_callback>* overloads[2];
342 for (int i = 0; i < 2; ++i)
343 if (operand[i]) overloads[i] = &operand[i]->crep()->m_operators[id]; else overloads[i] = 0;
345 std::size_t num_overloads[2];
346 for (int i = 0; i < 2; ++i)
347 if (overloads[i]) num_overloads[i] = overloads[i]->size(); else num_overloads[i] = 0;
349 for (int i = 0; i < 2; ++i)
350 if (operand[i] && operand[i]->crep()->get_class_type() == class_rep::lua_class)
352 /* // if this is a lua class we have to
353 // look in its table to see if there's
354 // any overload of this operator
355 detail::getref(L, operand[i]->crep()->table_ref());
356 lua_pushstring(L, get_operator_name(id));
357 lua_rawget(L, -2);
358 // if we have tha operator, set num_overloads to 1
359 if (lua_isfunction(L, -1)) num_overloads[i] = 1;
360 lua_pop(L, 2);*/
362 if (operand[i]->crep()->has_operator_in_lua(L, id))
363 num_overloads[i] = 1;
366 bool ambiguous = false;
367 int match_index = -1;
368 int min_match = std::numeric_limits<int>::max();
370 #ifdef LUABIND_NO_ERROR_CHECKING
372 if (num_overloads[0] == 1 && num_overloads[1] == 0)
374 operand_id = 0;
375 match_index = 0;
377 else if (num_overloads[0] == 0 && num_overloads[1] == 1)
379 operand_id = 1;
380 match_index = 0;
382 else
385 #endif
387 int num_params = lua_gettop(L);
389 // have look at the right operand.
390 // if the right operand is a class and
391 // not the same class as this, we have to
392 // try to match it's operators too
393 for (int i = 0; i < 2; ++i)
395 if (num_overloads[i])
397 if (operand[i]->crep()->get_class_type() == class_rep::lua_class)
399 // if this is a lua class
400 // and num_overloads is > 0
401 // it means that it has implemented
402 // this operator. Set match_index to
403 // 0 to signal that this operand has
404 // an overload, but leave the min_match
405 // at int-max to mark it as a last fallback
406 operand_id = i;
407 if (match_index == -1) match_index = 0;
409 else if (find_best_match(
411 , &overloads[i]->front()
412 , overloads[i]->size()
413 , sizeof(operator_callback)
414 , ambiguous
415 , min_match
416 , match_index
417 , num_params))
419 operand_id = i;
425 #ifdef LUABIND_NO_ERROR_CHECKING
429 #else
431 if (match_index == -1)
434 std::string msg("no operator ");
435 msg += get_operator_symbol(id);
436 msg += " matched the arguments (";
437 msg += stack_content_by_name(L, 1);
438 msg += ")\ncandidates are:\n";
440 for (int i = 0; i < 2; ++i)
442 if (overloads[i])
444 msg += get_overload_signatures(
446 , overloads[i]->begin()
447 , overloads[i]->end()
448 , get_operator_symbol(id));
450 else
452 // if num_overloads is > 0 it would mean that this is
453 // a lua class with this operator overloaded. And if
454 // that's the case, it should always match (and if an
455 // operator matches, we never come here).
456 assert(num_overloads[i] == 0 && "internal error");
459 lua_pushstring(L, msg.c_str());
461 lua_error(L);
463 else if (ambiguous)
466 std::string msg("call of overloaded operator ");
467 msg += get_operator_symbol(id);
468 msg += " (";
469 msg += stack_content_by_name(L, 1);
470 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
472 std::vector<const overload_rep_base*> candidates;
473 if (overloads[0])
474 find_exact_match(L, &overloads[0]->front(), overloads[0]->size(), sizeof(operator_callback), min_match, num_params, candidates);
476 if (overloads[1])
477 find_exact_match(L, &overloads[1]->front(), overloads[1]->size(), sizeof(operator_callback), min_match, num_params, candidates);
479 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), get_operator_symbol(id));
481 lua_pushstring(L, msg.c_str());
483 lua_error(L);
486 #endif
488 if (operand[operand_id]->crep()->get_class_type() == class_rep::lua_class)
490 detail::getref(L, operand[operand_id]->crep()->table_ref());
491 lua_pushstring(L, get_operator_name(id));
492 lua_rawget(L, -2);
493 lua_insert(L, -4); // move the function to the bottom
494 lua_pop(L, 1); // remove the table
495 lua_call(L, 2, 1);
496 return 1;
498 else
500 return (*overloads[operand_id])[match_index].call(L);
504 // this is called as metamethod __call on the class_rep.
505 int luabind::detail::class_rep::constructor_dispatcher(lua_State* L)
507 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
508 construct_rep* rep = &crep->m_constructor;
510 bool ambiguous = false;
511 int match_index = -1;
512 int min_match = std::numeric_limits<int>::max();
513 bool found;
515 #ifdef LUABIND_NO_ERROR_CHECKING
517 if (rep->overloads.size() == 1)
519 match_index = 0;
521 else
524 #endif
526 int num_params = lua_gettop(L) - 1;
527 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
529 #ifdef LUABIND_NO_ERROR_CHECKING
532 #else
534 if (!found)
537 std::string msg("no constructor of '");
538 msg += crep->name();
539 msg += "' matched the arguments (";
540 msg += stack_content_by_name(L, 2);
541 msg += ")\n candidates are:\n";
543 msg += get_overload_signatures(L, rep->overloads.begin(), rep->overloads.end(), crep->name());
545 lua_pushstring(L, msg.c_str());
547 lua_error(L);
549 else if (ambiguous)
552 std::string msg("call of overloaded constructor '");
553 msg += crep->m_name;
554 msg += "(";
555 msg += stack_content_by_name(L, 2);
556 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
558 std::vector<const overload_rep_base*> candidates;
559 find_exact_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), min_match, num_params, candidates);
560 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), crep->name());
562 lua_pushstring(L, msg.c_str());
564 lua_error(L);
567 #endif
569 #ifndef LUABIND_NO_EXCEPTIONS
574 #endif
576 void* object_ptr = rep->overloads[match_index].construct(L);
578 void* obj_rep;
579 void* held;
581 boost::tie(obj_rep,held) = crep->allocate(L);
583 if (crep->has_holder())
585 crep->m_construct_holder(held, object_ptr);
586 object_ptr = held;
588 new(obj_rep) object_rep(object_ptr, crep, object_rep::owner, crep->destructor());
590 detail::getref(L, crep->m_instance_metatable);
591 lua_setmetatable(L, -2);
592 return 1;
594 #ifndef LUABIND_NO_EXCEPTIONS
598 catch(const std::exception& e)
600 lua_pushstring(L, e.what());
602 catch(const char* s)
604 lua_pushstring(L, s);
606 catch(...)
609 std::string msg = crep->name();
610 msg += "() threw an exception";
611 lua_pushstring(L, msg.c_str());
615 // we can only reach this line if an exception was thrown
616 lua_error(L);
617 return 0; // will never be reached
619 #endif
623 // the functions dispatcher assumes the following:
624 // there is one upvalue that points to the method_rep that this dispatcher is to call
625 // the first parameter on the lua stack is an object_rep that points to the object the
626 // call is being made on
627 int luabind::detail::class_rep::function_dispatcher(lua_State* L)
629 method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
630 object_rep* obj = reinterpret_cast<object_rep*>(lua_touserdata(L, 1));
632 #ifndef LUABIND_NO_ERROR_CHECKING
634 if (is_class_object(L, 1) == 0)
637 std::string msg = "No self reference given as first parameter to member function '";
638 msg += rep->crep->name();
639 msg += ":";
640 msg += rep->name;
641 msg += "'. Have you used '.' instead of ':'?";
643 lua_pushstring(L, msg.c_str());
645 lua_error(L);
648 int p;
649 if (implicit_cast(obj->crep(), rep->crep->type(), p) < 0)
652 std::string msg = "invalid self reference given to '";
653 msg += rep->crep->name();
654 msg += ":";
655 msg += rep->name;
656 msg += "'";
657 lua_pushstring(L, msg.c_str());
659 lua_error(L);
662 #endif
664 bool ambiguous = false;
665 int match_index = -1;
666 int min_match = std::numeric_limits<int>::max();
667 bool found;
669 #ifdef LUABIND_NO_ERROR_CHECKING
670 if (rep->overloads().size() == 1)
672 match_index = 0;
674 else
676 #endif
678 int num_params = lua_gettop(L) - 1;
679 found = find_best_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), ambiguous, min_match, match_index, num_params);
681 #ifdef LUABIND_NO_ERROR_CHECKING
685 #else
687 if (!found)
690 std::string msg = "no overload of '";
691 msg += rep->crep->name();
692 msg += ":";
693 msg += rep->name;
694 msg += "' matched the arguments (";
695 msg += stack_content_by_name(L, 2);
696 msg += ")\ncandidates are:\n";
698 std::string function_name;
699 function_name += rep->crep->name();
700 function_name += ":";
701 function_name += rep->name;
703 msg += get_overload_signatures(L, rep->overloads().begin(), rep->overloads().end(), function_name);
705 lua_pushstring(L, msg.c_str());
707 lua_error(L);
709 else if (ambiguous)
712 std::string msg = "call of overloaded '";
713 msg += rep->crep->name();
714 msg += ":";
715 msg += rep->name;
716 msg += "(";
717 msg += stack_content_by_name(L, 2);
718 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
720 std::vector<const overload_rep_base*> candidates;
721 find_exact_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), min_match, num_params, candidates);
723 std::string function_name;
724 function_name += rep->crep->name();
725 function_name += ":";
726 function_name += rep->name;
728 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), function_name);
730 lua_pushstring(L, msg.c_str());
732 lua_error(L);
735 #endif
737 #ifndef LUABIND_NO_EXCEPTIONS
742 #endif
744 const overload_rep& o = rep->overloads()[match_index];
745 return o.call(L, *obj);
747 #ifndef LUABIND_NO_EXCEPTIONS
750 catch(const std::exception& e)
752 lua_pushstring(L, e.what());
754 catch (const char* s)
756 lua_pushstring(L, s);
758 catch(...)
760 std::string msg = rep->crep->name();
761 msg += ":";
762 msg += rep->name;
763 msg += "() threw an exception";
764 lua_pushstring(L, msg.c_str());
766 // we can only reach this line if an exception was thrown
767 lua_error(L);
768 return 0; // will never be reached
770 #endif
774 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo)
776 // If you hit this assert you are deriving from a type that is not registered
777 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
778 // Please note that if you don't need to have access to the base class or the
779 // conversion from the derived class to the base class, you don't need
780 // to tell luabind that it derives.
781 assert(binfo.base && "You cannot derive from an unregistered type");
783 class_rep* bcrep = binfo.base;
785 // import all functions from the base
786 for (std::map<const char*, method_rep, ltstr>::const_iterator i = bcrep->m_methods.begin();
787 i != bcrep->m_methods.end(); ++i)
789 // If we would assume that our base class will not be garbage collected until
790 // this class is collected, we wouldn't had to copy these strings.
791 method_rep& m = m_methods[i->first];
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 callback& m = m_getters[i->first];
810 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
811 m.func = i->second.func;
813 #ifndef LUABIND_NO_ERROR_CHECKING
814 m.match = i->second.match;
815 m.sig = i->second.sig;
816 #endif
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 callback& m = m_setters[i->first];
824 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
825 m.func = i->second.func;
827 #ifndef LUABIND_NO_ERROR_CHECKING
828 m.match = i->second.match;
829 m.sig = i->second.sig;
830 #endif
833 // import all static constants
834 for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin();
835 i != bcrep->m_static_constants.end(); ++i)
837 int& v = m_static_constants[i->first];
838 v = i->second;
841 // import all operators
842 for (int i = 0; i < number_of_operators; ++i)
844 for (std::vector<operator_callback>::const_iterator j = bcrep->m_operators[i].begin();
845 j != bcrep->m_operators[i].end(); ++j)
846 m_operators[i].push_back(*j);
849 // also, save the baseclass info to be used for typecasts
850 m_bases.push_back(binfo);
853 void luabind::detail::class_rep::add_function(const char* name, const overload_rep& o)
856 #ifdef LUABIND_DONT_COPY_STRINGS
857 detail::method_rep& method = m_methods[name];
858 method.name = name;
859 #else
860 m_strings.push_back(dup_string(name));
861 detail::method_rep& method = m_methods[m_strings.back()];
862 method.name = m_strings.back();
863 #endif
865 method.add_overload(o);
866 method.crep = this;
869 void luabind::detail::class_rep::add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
871 callback c;
872 c.func = g;
873 c.pointer_offset = 0;
874 #ifndef LUABIND_DONT_COPY_STRINGS
875 m_strings.push_back(dup_string(name));
876 m_getters[m_strings.back()] = c;
877 #else
878 m_getters[name] = c;
879 #endif
882 void luabind::detail::class_rep::add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
884 callback c;
885 c.func = s;
886 c.pointer_offset = 0;
887 #ifndef LUABIND_DONT_COPY_STRINGS
888 m_strings.push_back(dup_string(name));
889 m_setters[m_strings.back()] = c;
890 #else
891 m_setters[name] = c;
892 #endif
895 #ifndef LUABIND_NO_ERROR_CHECKING
896 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)
897 #else
898 void luabind::detail::class_rep::add_operator(lua_State*, int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
899 #endif
901 operator_callback o;
902 o.set_fun(func);
903 o.set_match_fun(matcher);
904 o.set_arity(arity);
906 #ifndef LUABIND_NO_ERROR_CHECKING
908 o.set_sig_fun(sig);
910 #endif
911 m_operators[op_id].push_back(o);
914 void luabind::detail::class_rep::add_static_constant(const char* name, int val)
916 #ifndef LUABIND_DONT_COPY_STRINGS
917 m_strings.push_back(dup_string(name));
918 m_static_constants[m_strings.back()] = val;
919 #else
920 m_static_constants[name] = val;
921 #endif
924 int luabind::detail::class_rep::super_callback(lua_State* L)
926 int args = lua_gettop(L);
928 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, lua_upvalueindex(2)));
929 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
930 class_rep* base = crep->bases()[0].base;
932 if (base->get_class_type() == class_rep::lua_class)
934 if (base->bases().empty())
936 obj->set_flags(obj->flags() & ~object_rep::call_super);
938 lua_pushstring(L, "super");
939 lua_pushnil(L);
940 lua_settable(L, LUA_GLOBALSINDEX);
942 else
944 lua_pushstring(L, "super");
945 lua_pushlightuserdata(L, base);
946 lua_pushvalue(L, lua_upvalueindex(2));
947 lua_pushcclosure(L, super_callback, 2);
948 lua_settable(L, LUA_GLOBALSINDEX);
951 detail::getref(L, base->table_ref());
952 lua_pushstring(L, "__init");
953 lua_gettable(L, -2);
954 lua_insert(L, 1);
955 lua_pop(L, 1);
957 lua_pushvalue(L, lua_upvalueindex(2));
958 lua_insert(L, 2);
960 lua_call(L, args + 1, 0);
962 // TODO: instead of clearing the global variable "super"
963 // store it temporarily in the registry. maybe we should
964 // have some kind of warning if the super global is used?
965 lua_pushstring(L, "super");
966 lua_pushnil(L);
967 lua_settable(L, LUA_GLOBALSINDEX);
969 else
971 obj->set_flags(obj->flags() & ~object_rep::call_super);
973 // we need to push some garbage at index 1 to make the construction work
974 lua_pushboolean(L, 1);
975 lua_insert(L, 1);
977 construct_rep* rep = &base->m_constructor;
979 bool ambiguous = false;
980 int match_index = -1;
981 int min_match = std::numeric_limits<int>::max();
982 bool found;
984 #ifdef LUABIND_NO_ERROR_CHECKING
986 if (rep->overloads.size() == 1)
988 match_index = 0;
990 else
993 #endif
995 int num_params = lua_gettop(L) - 1;
996 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
998 #ifdef LUABIND_NO_ERROR_CHECKING
1002 #else
1004 if (!found)
1007 std::string msg = "no constructor of '";
1008 msg += base->m_name;
1009 msg += "' matched the arguments (";
1010 msg += stack_content_by_name(L, 2);
1011 msg += ")";
1012 lua_pushstring(L, msg.c_str());
1014 lua_error(L);
1016 else if (ambiguous)
1019 std::string msg = "call of overloaded constructor '";
1020 msg += base->m_name;
1021 msg += "(";
1022 msg += stack_content_by_name(L, 2);
1023 msg += ")' is ambiguous";
1024 lua_pushstring(L, msg.c_str());
1026 lua_error(L);
1029 // TODO: should this be a warning or something?
1031 // since the derived class is a lua class
1032 // it may have reimplemented virtual functions
1033 // therefore, we have to instantiate the Basewrapper
1034 // if there is no basewrapper, throw a run-time error
1035 if (!rep->overloads[match_index].has_wrapped_construct())
1038 std::string msg = "Cannot derive from C++ class '";
1039 msg += base->name();
1040 msg += "'. It does not have a wrapped type";
1041 lua_pushstring(L, msg.c_str());
1043 lua_error(L);
1046 #endif
1048 #ifndef LUABIND_NO_EXCEPTIONS
1053 #endif
1054 void* storage_ptr = obj->ptr();
1056 if (!rep->overloads[match_index].has_wrapped_construct())
1058 // if the type doesn't have a wrapped type, use the ordinary constructor
1059 void* instance = rep->overloads[match_index].construct(L);
1061 if (crep->has_holder())
1063 crep->m_construct_holder(storage_ptr, instance);
1065 else
1067 obj->set_object(instance);
1070 else
1072 // get reference to lua object
1073 /* lua_pushvalue(L, lua_upvalueindex(2));
1074 detail::lua_reference ref;
1075 ref.set(L);
1076 void* instance = rep->overloads[match_index].construct_wrapped(L, ref);*/
1078 lua_pushvalue(L, lua_upvalueindex(2));
1079 weak_ref ref(L, -1);
1080 lua_pop(L, 1);
1081 void* instance = rep->overloads[match_index].construct_wrapped(L, ref);
1083 if (crep->has_holder())
1085 crep->m_construct_holder(storage_ptr, instance);
1087 else
1089 obj->set_object(instance);
1092 // TODO: is the wrapped type destructed correctly?
1093 // it should, since the destructor is either the wrapped type's
1094 // destructor or the base type's destructor, depending on wether
1095 // the type has a wrapped type or not.
1096 obj->set_destructor(base->destructor());
1097 return 0;
1099 #ifndef LUABIND_NO_EXCEPTIONS
1102 catch(const std::exception& e)
1104 lua_pushstring(L, e.what());
1106 catch(const char* s)
1108 lua_pushstring(L, s);
1110 catch(...)
1112 std::string msg = base->m_name;
1113 msg += "() threw an exception";
1114 lua_pushstring(L, msg.c_str());
1116 // can only be reached if an exception was thrown
1117 lua_error(L);
1118 #endif
1121 return 0;
1127 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L)
1129 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1130 detail::getref(L, crep->m_table_ref);
1131 lua_replace(L, 1);
1132 lua_rawset(L, -3);
1134 crep->m_operator_cache = 0; // invalidate cache
1136 return 0;
1139 int luabind::detail::class_rep::construct_lua_class_callback(lua_State* L)
1141 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1143 int args = lua_gettop(L);
1145 // lua stack: crep <arguments>
1147 lua_newtable(L);
1148 detail::lua_reference ref;
1149 ref.set(L);
1151 bool has_bases = !crep->bases().empty();
1153 if (has_bases)
1155 lua_pushstring(L, "super");
1156 lua_pushvalue(L, 1); // crep
1159 // lua stack: crep <arguments> "super" crep
1160 // or
1161 // lua stack: crep <arguments>
1163 // if we have a baseclass we set the flag to say that the super has not yet been called
1164 // we will use this flag later to check that it actually was called from __init()
1165 int flags = object_rep::lua_class | object_rep::owner | (has_bases ? object_rep::call_super : 0);
1167 // void* obj_ptr = lua_newuserdata(L, sizeof(object_rep));
1168 void* obj_ptr;
1169 void* held_storage;
1171 boost::tie(obj_ptr, held_storage) = crep->allocate(L);
1172 (new(obj_ptr) object_rep(crep, flags, ref))->set_object(held_storage);
1174 detail::getref(L, crep->metatable_ref());
1175 lua_setmetatable(L, -2);
1177 // lua stack: crep <arguments> "super" crep obj_ptr
1178 // or
1179 // lua stack: crep <arguments> obj_ptr
1181 if (has_bases) lua_pushvalue(L, -1); // obj_ptr
1182 lua_replace(L, 1); // obj_ptr
1184 // lua stack: obj_ptr <arguments> "super" crep obj_ptr
1185 // or
1186 // lua stack: obj_ptr <arguments>
1188 if (has_bases)
1190 lua_pushcclosure(L, super_callback, 2);
1191 // lua stack: crep <arguments> "super" function
1192 lua_settable(L, LUA_GLOBALSINDEX);
1195 // lua stack: crep <arguments>
1197 lua_pushvalue(L, 1);
1198 lua_insert(L, 1);
1200 detail::getref(L, crep->table_ref());
1201 lua_pushstring(L, "__init");
1202 lua_gettable(L, -2);
1204 #ifndef LUABIND_NO_ERROR_CHECKING
1206 // TODO: should this be a run-time error?
1207 // maybe the default behavior should be to just call
1208 // the base calss' constructor. We should register
1209 // the super callback funktion as __init
1210 if (!lua_isfunction(L, -1))
1213 std::string msg = crep->name();
1214 msg += ":__init is not defined";
1215 lua_pushstring(L, msg.c_str());
1217 lua_error(L);
1220 #endif
1222 lua_insert(L, 2); // function first on stack
1223 lua_pop(L, 1);
1224 // TODO: lua_call may invoke longjump! make sure we don't have any memory leaks!
1225 // we don't have any stack objects here
1226 lua_call(L, args, 0);
1228 #ifndef LUABIND_NO_ERROR_CHECKING
1230 object_rep* obj = static_cast<object_rep*>(obj_ptr);
1231 if (obj->flags() & object_rep::call_super)
1233 lua_pushstring(L, "derived class must call super on base");
1234 lua_error(L);
1237 #endif
1239 return 1;
1242 // called from the metamethod for __index
1243 // obj is the object pointer
1244 int luabind::detail::class_rep::lua_class_gettable(lua_State* L)
1246 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1247 class_rep* crep = obj->crep();
1249 #ifndef LUABIND_NO_ERROR_CHECKING
1251 if (obj->flags() & object_rep::call_super)
1253 lua_pushstring(L, "derived class must call super on base");
1254 lua_error(L);
1257 #endif
1259 // we have to ignore the first argument since this may point to
1260 // a method that is not present in this class (but in a subclass)
1262 // BUG: This might catch members called "__ok\0foobar"
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 obj->get_lua_table(L);
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 // BUG: This will not work with keys with extra nulls in them
1353 const char* key = lua_tostring(L, 2);
1356 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_setters.find(key);
1358 // if the strlen(key) is not the true length,
1359 // it means that the member-name contains
1360 // extra nulls. luabind does not support such
1361 // names as member names. So, use the lua
1362 // table as fall-back
1363 if (j == crep->m_setters.end()
1364 || std::strlen(key) != lua_strlen(L, 2))
1366 std::map<const char*, class_rep::callback, ltstr>::iterator k = crep->m_getters.find(key);
1368 #ifndef LUABIND_NO_ERROR_CHECKING
1370 if (k != crep->m_getters.end())
1373 std::string msg = "cannot set property '";
1374 msg += crep->name();
1375 msg += ".";
1376 msg += key;
1377 msg += "', because it's read only";
1378 lua_pushstring(L, msg.c_str());
1380 lua_error(L);
1383 #endif
1385 obj->get_lua_table(L);
1386 lua_replace(L, 1);
1387 lua_settable(L, 1);
1389 else
1391 // the name is a data member
1392 j->second.func(L, j->second.pointer_offset);
1395 return 0;
1398 int luabind::detail::class_rep::static_class_gettable(lua_State* L)
1400 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1402 detail::getref(L, crep->m_table_ref);
1403 lua_pushvalue(L, 2);
1404 lua_gettable(L, -2);
1405 if (!lua_isnil(L, -1)) return 1;
1406 else lua_pop(L, 2);
1408 const char* key = lua_tostring(L, 2);
1410 if (std::strlen(key) != lua_strlen(L, 2))
1412 lua_pushnil(L);
1413 return 1;
1416 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1417 if (i != crep->m_methods.end())
1419 // the name is a method, return it
1420 lua_pushlightuserdata(L, &i->second);
1421 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1422 return 1;
1425 std::map<const char*, int, ltstr>::const_iterator j = crep->m_static_constants.find(key);
1427 if (j != crep->m_static_constants.end())
1429 lua_pushnumber(L, j->second);
1430 return 1;
1433 #ifndef LUABIND_NO_ERROR_CHECKING
1436 std::string msg = "no static '";
1437 msg += key;
1438 msg += "' in class '";
1439 msg += crep->name();
1440 msg += "'";
1441 lua_pushstring(L, msg.c_str());
1443 lua_error(L);
1445 #endif
1447 lua_pushnil(L);
1449 return 1;
1452 bool luabind::detail::is_class_rep(lua_State* L, int index)
1454 if (lua_getmetatable(L, index) == 0) return false;
1456 lua_pushstring(L, "__luabind_classrep");
1457 lua_gettable(L, -2);
1458 if (lua_toboolean(L, -1))
1460 lua_pop(L, 2);
1461 return true;
1464 lua_pop(L, 2);
1465 return false;
1468 void luabind::detail::finalize(lua_State* L, class_rep* crep)
1470 if (crep->get_class_type() != class_rep::lua_class) return;
1472 // lua_pushvalue(L, -1); // copy the object ref
1473 detail::getref(L, crep->table_ref());
1474 lua_pushstring(L, "__finalize");
1475 lua_gettable(L, -2);
1476 lua_remove(L, -2);
1478 if (lua_isnil(L, -1))
1480 lua_pop(L, 1);
1482 else
1484 lua_pushvalue(L, -2);
1485 lua_call(L, 1, 0);
1488 for (std::vector<class_rep::base_info>::const_iterator
1489 i = crep->bases().begin(); i != crep->bases().end(); ++i)
1491 if (i->base) finalize(L, i->base);
1495 void* luabind::detail::class_rep::convert_to(
1496 LUABIND_TYPE_INFO target_type
1497 , const object_rep* obj
1498 , void* target_memory) const
1500 // TODO: since this is a member function, we don't have to use the accesor functions for
1501 // the types and the extractor
1503 assert(obj == 0 || obj->crep() == this);
1505 int steps = 0;
1506 int offset = 0;
1507 if (!(LUABIND_TYPE_INFO_EQUAL(holder_type(), target_type))
1508 && !(LUABIND_TYPE_INFO_EQUAL(const_holder_type(), target_type)))
1510 steps = implicit_cast(this, target_type, offset);
1513 // should never be called with a type that can't be cast
1514 assert((steps >= 0) && "internal error, please report");
1516 if (LUABIND_TYPE_INFO_EQUAL(target_type, holder_type()))
1518 if (obj == 0)
1520 // we are trying to convert nil to a holder type
1521 m_default_construct_holder(target_memory);
1522 return target_memory;
1524 // if the type we are trying to convert to is the holder_type
1525 // it means that his crep has a holder_type (since it would have
1526 // been invalid otherwise, and T cannot be invalid). It also means
1527 // that we need no conversion, since the holder_type is what the
1528 // object points to.
1529 return obj->ptr();
1532 if (LUABIND_TYPE_INFO_EQUAL(target_type, const_holder_type()))
1534 if (obj == 0)
1536 // we are trying to convert nil to a const holder type
1537 m_default_construct_const_holder(target_memory);
1538 return target_memory;
1541 if (obj->flags() & object_rep::constant)
1543 // we are holding a constant
1544 return obj->ptr();
1546 else
1548 // we are holding a non-constant, we need to convert it
1549 // to a const_holder.
1550 m_const_converter(obj->ptr(), target_memory);
1551 return target_memory;
1555 void* raw_pointer;
1557 if (has_holder())
1559 assert(obj);
1560 // this means that we have a holder type where the
1561 // raw-pointer needs to be extracted
1562 raw_pointer = extractor()(obj->ptr());
1564 else
1566 if (obj == 0) raw_pointer = 0;
1567 else raw_pointer = obj->ptr();
1570 return static_cast<char*>(raw_pointer) + offset;
1573 void luabind::detail::class_rep::cache_operators(lua_State* L)
1575 m_operator_cache = 0x1;
1577 for (int i = 0; i < number_of_operators; ++i)
1579 getref(L, table_ref());
1580 lua_pushstring(L, get_operator_name(i));
1581 lua_rawget(L, -2);
1583 if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1);
1585 lua_pop(L, 2);
1589 bool luabind::detail::class_rep::has_operator_in_lua(lua_State* L, int id)
1591 if ((m_operator_cache & 0x1) == 0)
1592 cache_operators(L);
1594 const int mask = 1 << (id + 1);
1596 return (m_operator_cache & mask) != 0;
1599 void luabind::detail::class_rep::add_method(lua_State* L, const char* name, detail::method_rep& m)
1601 detail::getref(L, table_ref());
1602 lua_pushstring(L, name);
1603 lua_gettable(L, -2);
1605 if (lua_isnil(L, -1) || !lua_iscfunction(L, -1))
1607 lua_pop(L, 1);
1608 lua_pushstring(L, name);
1609 lua_pushlightuserdata(L, const_cast<void*>((const void*)&m));
1610 lua_pushcclosure(L, function_dispatcher, 1);
1611 lua_settable(L, -3);
1612 lua_pop(L, 1);
1614 else
1616 lua_getupvalue(L, -1, 1);
1617 method_rep* inherited = static_cast<method_rep*>(lua_touserdata(L, -1));
1619 for (std::vector<overload_rep>::const_iterator i = inherited->overloads().begin();
1620 i != inherited->overloads().end(); ++i)
1622 m.add_overload(*i);
1625 detail::getref(L, table_ref());
1626 lua_pushstring(L, name);
1627 lua_pushlightuserdata(L, const_cast<void*>((const void*)&m));
1628 lua_pushcclosure(L, function_dispatcher, 1);
1629 lua_settable(L, -3);
1630 lua_pop(L, 4);
1634 const class_rep::property_map& luabind::detail::class_rep::properties() const
1636 return m_getters;