applied patch from Rene Rivera to make it compile in Metrowerks 8.x
[luabind.git] / src / class_rep.cpp
blob5c23ded0674f8ad91484d6c36658cb7947e8cb3b
1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
23 #include <luabind/lua_include.hpp>
25 #define LUABIND_BUILDING
27 #include <luabind/luabind.hpp>
28 #include <utility>
30 using namespace luabind::detail;
33 #ifndef LUABIND_NO_ERROR_CHECKING
35 std::string luabind::detail::get_overload_signatures_candidates(lua_State* L, std::vector<const overload_rep_base*>::iterator start, std::vector<const overload_rep_base*>::iterator end, std::string name)
37 std::string s;
38 for (; start != end; ++start)
40 s += name;
41 (*start)->get_signature(L, s);
42 s += "\n";
44 return s;
47 #endif
50 luabind::detail::class_rep::class_rep(LUABIND_TYPE_INFO type
51 , const char* name
52 , lua_State* L
53 , void(*destructor)(void*)
54 , void(*const_holder_destructor)(void*)
55 , LUABIND_TYPE_INFO holder_type
56 , LUABIND_TYPE_INFO const_holder_type
57 , void*(*extractor)(void*)
58 , const void*(*const_extractor)(void*)
59 , void(*const_converter)(void*,void*)
60 , void(*construct_holder)(void*,void*)
61 , void(*construct_const_holder)(void*,void*)
62 , int holder_size
63 , int holder_alignment)
65 : m_type(type)
66 , m_holder_type(holder_type)
67 , m_const_holder_type(const_holder_type)
68 , m_extractor(extractor)
69 , m_const_extractor(const_extractor)
70 , m_const_converter(const_converter)
71 , m_construct_holder(construct_holder)
72 , m_construct_const_holder(construct_const_holder)
73 , m_holder_size(holder_size)
74 , m_holder_alignment(holder_alignment)
75 , m_name(name)
76 , m_table_ref(LUA_NOREF)
77 , m_class_type(cpp_class)
78 , m_destructor(destructor)
79 , m_const_holder_destructor(const_holder_destructor)
80 , m_operator_cache(0)
82 assert(m_holder_alignment >= 1 && "internal error");
84 lua_newtable(L);
85 m_table_ref = detail::ref(L);
87 class_registry* r = class_registry::get_registry(L);
88 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
90 detail::getref(L, r->cpp_class());
91 lua_setmetatable(L, -2);
93 lua_pushvalue(L, -1); // duplicate our user data
94 m_self_ref = detail::ref(L); // pop one of them
96 m_instance_metatable = r->cpp_instance();
99 luabind::detail::class_rep::class_rep(lua_State* L, const char* name)
100 : m_type(LUABIND_INVALID_TYPE_INFO)
101 , m_holder_type(LUABIND_INVALID_TYPE_INFO)
102 , m_const_holder_type(LUABIND_INVALID_TYPE_INFO)
103 , m_extractor(0)
104 , m_const_extractor(0)
105 , m_const_converter(0)
106 , m_construct_holder(0)
107 , m_construct_const_holder(0)
108 , m_holder_size(0)
109 , m_holder_alignment(1)
110 , m_class_type(lua_class)
111 , m_destructor(0)
112 , m_const_holder_destructor(0)
113 , m_operator_cache(0)
115 #ifndef LUABIND_DONT_COPY_STRINGS
116 m_strings.push_back(detail::dup_string(name));
117 m_name = m_strings.back();
118 #else
119 m_name = name;
120 #endif
121 lua_newtable(L);
122 m_table_ref = detail::ref(L);
124 class_registry* r = class_registry::get_registry(L);
125 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
127 detail::getref(L, r->lua_class());
128 lua_setmetatable(L, -2);
129 lua_pushvalue(L, -1); // duplicate our user data
130 m_self_ref = detail::ref(L); // pop one of them
132 m_instance_metatable = r->lua_instance();
135 luabind::detail::class_rep::~class_rep()
137 #ifndef LUABIND_DONT_COPY_STRINGS
138 for (std::vector<char*>::iterator i = m_strings.begin();
139 i != m_strings.end(); ++i)
141 delete[] *i;
143 #endif
146 std::pair<void*,void*>
147 luabind::detail::class_rep::allocate(lua_State* L) const
149 const int overlap = sizeof(object_rep)&(m_holder_alignment-1);
150 const int padding = overlap==0?0:m_holder_alignment-overlap;
151 const int size = sizeof(object_rep) + padding + m_holder_size;
153 char* mem = static_cast<char*>(lua_newuserdata(L, size));
154 char* ptr = mem + sizeof(object_rep) + padding;
156 return std::pair<void*,void*>(mem,ptr);
159 //#include <iostream>
160 // lua stack: userdata, key
161 int luabind::detail::class_rep::gettable(lua_State* L)
163 // if key is nil, return nil
164 if (lua_isnil(L, 2))
166 lua_pushnil(L);
167 return 1;
170 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
172 // we have to ignore the first argument since this may point to
173 // a method that is not present in this class (but in a subclass)
174 const char* key = lua_tostring(L, 2);
176 // special case to see if this is a null-pointer
177 if (key && !std::strcmp(key, "__ok"))
179 class_rep* crep = obj->crep();
181 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
182 : obj->ptr();
184 lua_pushboolean(L, p != 0);
185 return 1;
188 detail::getref(L, obj->crep()->table_ref());
189 lua_pushvalue(L, 2);
190 lua_gettable(L, -2);
192 if (!lua_isnil(L, -1))
194 // std::cout << "method found in lua table: " << key << "\n";
195 lua_remove(L, -2); // more table
196 return 1;
199 lua_pop(L, 2);
201 std::map<const char*, method_rep, ltstr>::iterator i = m_methods.find(key);
203 if (i != m_methods.end())
205 // the name is a method, return it
206 lua_pushlightuserdata(L, &i->second);
207 lua_pushcclosure(L, function_dispatcher, 1);
208 return 1;
211 std::map<const char*, callback, ltstr>::iterator j = m_getters.find(key);
212 if (j != m_getters.end())
214 // the name is a data member
215 return j->second.func(L, j->second.pointer_offset);
218 lua_pushnil(L);
219 return 1;
222 // called from the metamethod for __newindex
223 // the object pointer is passed on the lua stack
224 // lua stack: userdata, key, value
225 bool luabind::detail::class_rep::settable(lua_State* L)
227 // if the key is 'nil' fail
228 if (lua_isnil(L, 2)) return false;
230 // we have to ignore the first argument since this may point to
231 // a method that is not present in this class (but in a subclass)
232 const char* key = lua_tostring(L, 2);
233 std::map<const char*, callback, ltstr>::iterator j = m_setters.find(key);
234 if (j != m_setters.end())
236 // the name is a data member
237 j->second.func(L, j->second.pointer_offset);
238 return true;
241 if (m_getters.find(key) != m_getters.end())
243 // this means that we have a getter but no
244 // setter for an attribute. We will then fail
245 // because that attribute is read-only
246 return false;
249 // set the attribute to the object's table
250 getref(L, table_ref());
251 lua_pushvalue(L, 2);
252 lua_pushvalue(L, 3);
253 lua_settable(L, 4);
254 lua_pop(L, 3);
255 return true;
258 int class_rep::gettable_dispatcher(lua_State* L)
260 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
261 return obj->crep()->gettable(L);
264 // this is called as __newindex metamethod on every instance of this class
265 int luabind::detail::class_rep::settable_dispatcher(lua_State* L)
267 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
269 bool success = obj->crep()->settable(L);
271 #ifndef LUABIND_NO_ERROR_CHECKING
273 if (!success)
275 // this block is needed to make sure the std::string is destructed before
276 // lua_error() is called
277 #ifdef BOOST_MSVC
279 // msvc has a bug which deletes the string twice, that's
280 // why we have to create it on the heap
281 std::string* msg = new std::string("cannot set attribute '");
282 *msg += obj->crep()->m_name;
283 *msg += ".";
284 *msg += lua_tostring(L, -2);
285 *msg += "'";
286 lua_pushstring(L, msg->c_str());
287 delete msg;
289 #else
291 std::string msg = "cannot set attribute '";
292 msg += obj->crep()->m_name;
293 msg += ".";
294 msg += lua_tostring(L, -2);
295 msg += "'";
296 lua_pushstring(L, msg.c_str());
298 #endif
299 lua_error(L);
302 #endif
304 return 0;
308 int luabind::detail::class_rep::operator_dispatcher(lua_State* L)
310 int id = static_cast<int>(lua_tonumber(L, lua_upvalueindex(1)));
312 int operand_id = 0;
314 object_rep* operand[2];
315 for (int i = 0; i < 2; ++i)
316 operand[i] = detail::is_class_object(L, i + 1);
318 // we cannot compare the types here, we have to compare the pointers of the class_reps
319 // since all lua-classes have the same type (LUABIND_INVALID_TYPE_INFO)
320 if (operand[0] && operand[1])
321 if (operand[0]->crep() == operand[1]->crep()) operand[1] = 0;
323 std::vector<operator_callback>* overloads[2];
324 for (int i = 0; i < 2; ++i)
325 if (operand[i]) overloads[i] = &operand[i]->crep()->m_operators[id]; else overloads[i] = 0;
327 std::size_t num_overloads[2];
328 for (int i = 0; i < 2; ++i)
329 if (overloads[i]) num_overloads[i] = overloads[i]->size(); else num_overloads[i] = 0;
331 for (int i = 0; i < 2; ++i)
332 if (operand[i] && operand[i]->crep()->get_class_type() == class_rep::lua_class)
334 /* // if this is a lua class we have to
335 // look in its table to see if there's
336 // any overload of this operator
337 detail::getref(L, operand[i]->crep()->table_ref());
338 lua_pushstring(L, get_operator_name(id));
339 lua_rawget(L, -2);
340 // if we have tha operator, set num_overloads to 1
341 if (lua_isfunction(L, -1)) num_overloads[i] = 1;
342 lua_pop(L, 2);*/
344 if (operand[i]->crep()->has_operator_in_lua(L, id))
345 num_overloads[i] = 1;
348 bool ambiguous = false;
349 int match_index = -1;
350 int min_match = std::numeric_limits<int>::max();
352 #ifdef LUABIND_NO_ERROR_CHECKING
354 if (num_overloads[0] == 1 && num_overloads[1] == 0)
356 operand_id = 0;
357 match_index = 0;
359 else if (num_overloads[0] == 0 && num_overloads[1] == 1)
361 operand_id = 1;
362 match_index = 0;
364 else
367 #endif
369 int num_params = lua_gettop(L);
371 // have look at the right operand.
372 // if the right operand is a class and
373 // not the same class as this, we have to
374 // try to match it's operators too
375 for (int i = 0; i < 2; ++i)
377 if (num_overloads[i])
379 if (operand[i]->crep()->get_class_type() == class_rep::lua_class)
381 // if this is a lua class
382 // and num_overloads is > 0
383 // it means that it has implemented
384 // this operator. Set match_index to
385 // 0 to signal that this operand has
386 // an overload, but leave the min_match
387 // at int-max to mark it as a last fallback
388 operand_id = i;
389 if (match_index == -1) match_index = 0;
391 else if (find_best_match(
393 , &overloads[i]->front()
394 , overloads[i]->size()
395 , sizeof(operator_callback)
396 , ambiguous
397 , min_match
398 , match_index
399 , num_params))
401 operand_id = i;
407 #ifdef LUABIND_NO_ERROR_CHECKING
411 #else
413 if (match_index == -1)
415 // this block is needed to make sure the std::string is destructed before
416 // lua_error() is called
418 std::string msg = "no operator ";
419 msg += get_operator_symbol(id);
420 msg += " matched the arguments (";
421 msg += stack_content_by_name(L, 1);
422 msg += ")\ncandidates are:\n";
424 for (int i = 0; i < 2; ++i)
426 if (overloads[i])
428 msg += get_overload_signatures(
430 , overloads[i]->begin()
431 , overloads[i]->end()
432 , get_operator_symbol(id));
434 else
436 // if num_overloads is > 0 it would mean that this is
437 // a lua class with this operator overloaded. And if
438 // that's the case, it should always match (and if an
439 // operator matches, we never come here).
440 assert(num_overloads[i] == 0 && "internal error");
444 lua_pushstring(L, msg.c_str());
446 lua_error(L);
448 else if (ambiguous)
450 // this block is needed to make sure the std::string is destructed before
451 // lua_error() is called
453 std::string msg = "call of overloaded operator ";
454 msg += get_operator_symbol(id);
455 msg += " (";
456 msg += stack_content_by_name(L, 1);
457 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
459 std::vector<const overload_rep_base*> candidates;
460 if (overloads[0])
461 find_exact_match(L, &overloads[0]->front(), overloads[0]->size(), sizeof(operator_callback), min_match, num_params, candidates);
463 if (overloads[1])
464 find_exact_match(L, &overloads[1]->front(), overloads[1]->size(), sizeof(operator_callback), min_match, num_params, candidates);
466 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), get_operator_symbol(id));
468 lua_pushstring(L, msg.c_str());
470 lua_error(L);
473 #endif
475 if (operand[operand_id]->crep()->get_class_type() == class_rep::lua_class)
477 detail::getref(L, operand[operand_id]->crep()->table_ref());
478 lua_pushstring(L, get_operator_name(id));
479 lua_rawget(L, -2);
480 lua_insert(L, -4); // move the function to the bottom
481 lua_pop(L, 1); // remove the table
482 lua_call(L, 2, 1);
483 return 1;
485 else
487 return (*overloads[operand_id])[match_index].call(L);
491 // this is called as metamethod __call on the class_rep.
492 int luabind::detail::class_rep::constructor_dispatcher(lua_State* L)
494 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
495 construct_rep* rep = &crep->m_constructor;
497 bool ambiguous = false;
498 int match_index = -1;
499 int min_match = std::numeric_limits<int>::max();
500 bool found;
502 #ifdef LUABIND_NO_ERROR_CHECKING
504 if (rep->overloads.size() == 1)
506 match_index = 0;
508 else
511 #endif
513 int num_params = lua_gettop(L) - 1;
514 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
516 #ifdef LUABIND_NO_ERROR_CHECKING
519 #else
521 if (!found)
523 // this block is needed to make sure the std::string is destructed before
524 // lua_error() is called
526 std::string msg = "no constructor of '";
527 msg += crep->name();
528 msg += "' matched the arguments (";
529 msg += stack_content_by_name(L, 2);
530 msg += ")\n candidates are:\n";
532 msg += get_overload_signatures(L, rep->overloads.begin(), rep->overloads.end(), crep->name());
534 lua_pushstring(L, msg.c_str());
536 lua_error(L);
538 else if (ambiguous)
540 // this block is needed to make sure the std::string is destructed before
541 // lua_error() is called
543 std::string msg = "call of overloaded constructor '";
544 msg += crep->m_name;
545 msg += "(";
546 msg += stack_content_by_name(L, 2);
547 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
549 std::vector<const overload_rep_base*> candidates;
550 find_exact_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), min_match, num_params, candidates);
551 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), crep->name());
553 lua_pushstring(L, msg.c_str());
555 lua_error(L);
558 #endif
560 #ifndef LUABIND_NO_EXCEPTIONS
565 #endif
567 void* object_ptr = rep->overloads[match_index].construct(L);
569 void* obj_rep;
570 void* held;
572 boost::tie(obj_rep,held) = crep->allocate(L);
574 if (crep->has_holder())
576 crep->m_construct_holder(held, object_ptr);
577 object_ptr = held;
579 new(obj_rep) object_rep(object_ptr, crep, object_rep::owner, crep->destructor());
581 detail::getref(L, crep->m_instance_metatable);
582 lua_setmetatable(L, -2);
583 return 1;
585 #ifndef LUABIND_NO_EXCEPTIONS
589 catch(const std::exception& e)
591 lua_pushstring(L, e.what());
593 catch(const char* s)
595 lua_pushstring(L, s);
597 catch(...)
600 std::string msg = crep->name();
601 msg += "() threw an exception";
602 lua_pushstring(L, msg.c_str());
606 // we can only reach this line if an exception was thrown
607 lua_error(L);
608 return 0; // will never be reached
610 #endif
614 // the functions dispatcher assumes the following:
615 // there is one upvalue that points to the method_rep that this dispatcher is to call
616 // the first parameter on the lua stack is an object_rep that points to the object the
617 // call is being made on
618 int luabind::detail::class_rep::function_dispatcher(lua_State* L)
620 method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
621 object_rep* obj = reinterpret_cast<object_rep*>(lua_touserdata(L, 1));
623 #ifndef LUABIND_NO_ERROR_CHECKING
625 if (is_class_object(L, 1) == 0)
628 std::string msg = "No self reference given as first parameter to member function '";
629 msg += rep->crep->name();
630 msg += ":";
631 msg += rep->name;
632 msg += "'. Have you used '.' instead of ':'?";
634 lua_pushstring(L, msg.c_str());
636 lua_error(L);
639 int p;
640 if (implicit_cast(obj->crep(), rep->crep->type(), p) < 0)
643 std::string msg = "invalid self reference given to '";
644 msg += rep->crep->name();
645 msg += ":";
646 msg += rep->name;
647 msg += "'";
648 lua_pushstring(L, msg.c_str());
650 lua_error(L);
653 #endif
655 bool ambiguous = false;
656 int match_index = -1;
657 int min_match = std::numeric_limits<int>::max();
658 bool found;
660 #ifdef LUABIND_NO_ERROR_CHECKING
661 if (rep->overloads().size() == 1)
663 match_index = 0;
665 else
667 #endif
669 int num_params = lua_gettop(L) - 1;
670 found = find_best_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), ambiguous, min_match, match_index, num_params);
672 #ifdef LUABIND_NO_ERROR_CHECKING
676 #else
678 if (!found)
681 std::string msg = "no overload of '";
682 msg += rep->crep->name();
683 msg += ":";
684 msg += rep->name;
685 msg += "' matched the arguments (";
686 msg += stack_content_by_name(L, 2);
687 msg += ")\ncandidates are:\n";
689 std::string function_name;
690 function_name += rep->crep->name();
691 function_name += ":";
692 function_name += rep->name;
694 msg += get_overload_signatures(L, rep->overloads().begin(), rep->overloads().end(), function_name);
696 lua_pushstring(L, msg.c_str());
698 lua_error(L);
700 else if (ambiguous)
703 std::string msg = "call of overloaded '";
704 msg += rep->crep->name();
705 msg += ":";
706 msg += rep->name;
707 msg += "(";
708 msg += stack_content_by_name(L, 2);
709 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
711 std::vector<const overload_rep_base*> candidates;
712 find_exact_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), min_match, num_params, candidates);
714 std::string function_name;
715 function_name += rep->crep->name();
716 function_name += ":";
717 function_name += rep->name;
719 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), function_name);
721 lua_pushstring(L, msg.c_str());
723 lua_error(L);
726 #endif
728 #ifndef LUABIND_NO_EXCEPTIONS
733 #endif
735 const overload_rep& o = rep->overloads()[match_index];
736 return o.call(L, *obj);
738 #ifndef LUABIND_NO_EXCEPTIONS
741 catch(const std::exception& e)
743 lua_pushstring(L, e.what());
745 catch (const char* s)
747 lua_pushstring(L, s);
749 catch(...)
751 std::string msg = rep->crep->name();
752 msg += ":";
753 msg += rep->name;
754 msg += "() threw an exception";
755 lua_pushstring(L, msg.c_str());
757 // we can only reach this line if an exception was thrown
758 lua_error(L);
759 return 0; // will never be reached
761 #endif
765 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo)
767 // If you hit this assert you are deriving from a type that is not registered
768 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
769 // Please note that if you don't need to have access to the base class or the
770 // conversion from the derived class to the base class, you don't need
771 // to tell luabind that it derives.
772 assert(binfo.base && "You cannot derive from an unregistered type");
774 class_rep* bcrep = binfo.base;
776 // import all functions from the base
777 for (std::map<const char*, method_rep, ltstr>::const_iterator i = bcrep->m_methods.begin();
778 i != bcrep->m_methods.end(); ++i)
780 // If we would assume that our base class will not be garbage collected until
781 // this class is collected, we wouldn't had to copy these strings.
782 #ifndef LUABIND_DONT_COPY_STRINGS
783 m_strings.push_back(dup_string(i->first));
784 method_rep& m = m_methods[m_strings.back()];
785 #else
786 method_rep& m = m_methods[i->first];
787 #endif
788 m.name = i->first;
789 m.crep = this;
791 for (std::vector<overload_rep>::const_iterator j = i->second.overloads().begin();
792 j != i->second.overloads().end(); ++j)
794 overload_rep o = *j;
795 o.add_offset(binfo.pointer_offset);
796 m.add_overload(o);
800 // import all getters from the base
801 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_getters.begin();
802 i != bcrep->m_getters.end(); ++i)
804 #ifndef LUABIND_DONT_COPY_STRINGS
805 m_strings.push_back(dup_string(i->first));
806 callback& m = m_getters[m_strings.back()];
807 #else
808 callback& m = m_getters[i->first];
809 #endif
810 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
811 m.func = i->second.func;
814 // import all setters from the base
815 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_setters.begin();
816 i != bcrep->m_setters.end(); ++i)
818 #ifndef LUABIND_DONT_COPY_STRINGS
819 // TODO: optimize this by not copying the string if it already exists in m_setters.
820 // This goes for m_getters, m_static_constants and m_functions too. Both here
821 // in add_base() and in the add_function(), add_getter() ... functions.
822 m_strings.push_back(dup_string(i->first));
823 callback& m = m_setters[m_strings.back()];
824 #else
825 callback& m = m_setters[i->first];
826 #endif
827 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
828 m.func = i->second.func;
831 // import all static constants
832 for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin();
833 i != bcrep->m_static_constants.end(); ++i)
835 #ifndef LUABIND_DONT_COPY_STRINGS
836 m_strings.push_back(dup_string(i->first));
837 int& v = m_static_constants[m_strings.back()];
838 #else
839 int& v = m_static_constants[i->first];
840 #endif
841 v = i->second;
844 // import all operators
845 for (int i = 0; i < number_of_operators; ++i)
847 for (std::vector<operator_callback>::const_iterator j = bcrep->m_operators[i].begin();
848 j != bcrep->m_operators[i].end(); ++j)
849 m_operators[i].push_back(*j);
852 // also, save the baseclass info to be used for typecasts
853 m_bases.push_back(binfo);
856 void luabind::detail::class_rep::add_function(const char* name, const overload_rep& o)
859 #ifdef LUABIND_DONT_COPY_STRINGS
860 detail::method_rep& method = m_methods[name];
861 method.name = name;
862 #else
863 m_strings.push_back(dup_string(name));
864 detail::method_rep& method = m_methods[m_strings.back()];
865 method.name = m_strings.back();
866 #endif
868 method.add_overload(o);
869 method.crep = this;
872 void luabind::detail::class_rep::add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
874 callback c;
875 c.func = g;
876 c.pointer_offset = 0;
877 #ifndef LUABIND_DONT_COPY_STRINGS
878 m_strings.push_back(dup_string(name));
879 m_getters[m_strings.back()] = c;
880 #else
881 m_getters[name] = c;
882 #endif
885 void luabind::detail::class_rep::add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
887 callback c;
888 c.func = s;
889 c.pointer_offset = 0;
890 #ifndef LUABIND_DONT_COPY_STRINGS
891 m_strings.push_back(dup_string(name));
892 m_setters[m_strings.back()] = c;
893 #else
894 m_setters[name] = c;
895 #endif
898 #ifndef LUABIND_NO_ERROR_CHECKING
899 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)
900 #else
901 void luabind::detail::class_rep::add_operator(lua_State*, int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
902 #endif
904 operator_callback o;
905 o.set_fun(func);
906 o.set_match_fun(matcher);
907 o.set_arity(arity);
909 #ifndef LUABIND_NO_ERROR_CHECKING
911 o.set_sig_fun(sig);
913 #endif
914 m_operators[op_id].push_back(o);
917 void luabind::detail::class_rep::add_static_constant(const char* name, int val)
919 #ifndef LUABIND_DONT_COPY_STRINGS
920 m_strings.push_back(dup_string(name));
921 m_static_constants[m_strings.back()] = val;
922 #else
923 m_static_constants[name] = val;
924 #endif
927 int luabind::detail::class_rep::super_callback(lua_State* L)
929 int args = lua_gettop(L);
931 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, lua_upvalueindex(2)));
932 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
933 class_rep* base = crep->bases()[0].base;
935 if (base->get_class_type() == class_rep::lua_class)
937 if (base->bases().empty())
939 obj->set_flags(obj->flags() & ~object_rep::call_super);
941 lua_pushstring(L, "super");
942 lua_pushnil(L);
943 lua_settable(L, LUA_GLOBALSINDEX);
945 else
947 lua_pushstring(L, "super");
948 lua_pushlightuserdata(L, base);
949 lua_pushvalue(L, lua_upvalueindex(2));
950 lua_pushcclosure(L, super_callback, 2);
951 lua_settable(L, LUA_GLOBALSINDEX);
954 detail::getref(L, base->table_ref());
955 lua_pushstring(L, "__init");
956 lua_gettable(L, -2);
957 lua_insert(L, 1);
958 lua_pop(L, 1);
960 lua_pushvalue(L, lua_upvalueindex(2));
961 lua_insert(L, 2);
963 lua_call(L, args + 1, 0);
965 // TODO: instead of clearing the global variable "super"
966 // store it temporarily in the registry. maybe we should
967 // have some kind of warning if the super global is used?
968 lua_pushstring(L, "super");
969 lua_pushnil(L);
970 lua_settable(L, LUA_GLOBALSINDEX);
972 else
974 obj->set_flags(obj->flags() & ~object_rep::call_super);
976 // we need to push some garbage at index 1 to make the construction work
977 lua_pushboolean(L, 1);
978 lua_insert(L, 1);
980 construct_rep* rep = &base->m_constructor;
982 bool ambiguous = false;
983 int match_index = -1;
984 int min_match = std::numeric_limits<int>::max();
985 bool found;
987 #ifdef LUABIND_NO_ERROR_CHECKING
989 if (rep->overloads.size() == 1)
991 match_index = 0;
993 else
996 #endif
998 int num_params = lua_gettop(L) - 1;
999 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
1001 #ifdef LUABIND_NO_ERROR_CHECKING
1005 #else
1007 if (!found)
1010 std::string msg = "no constructor of '";
1011 msg += base->m_name;
1012 msg += "' matched the arguments (";
1013 msg += stack_content_by_name(L, 2);
1014 msg += ")";
1015 lua_pushstring(L, msg.c_str());
1017 lua_error(L);
1019 else if (ambiguous)
1022 std::string msg = "call of overloaded constructor '";
1023 msg += base->m_name;
1024 msg += "(";
1025 msg += stack_content_by_name(L, 2);
1026 msg += ")' is ambiguous";
1027 lua_pushstring(L, msg.c_str());
1029 lua_error(L);
1032 // TODO: should this be a warning or something?
1034 // since the derived class is a lua class
1035 // it may have reimplemented virtual functions
1036 // therefore, we have to instantiate the Basewrapper
1037 // if there is no basewrapper, throw a run-time error
1038 if (!rep->overloads[match_index].has_wrapped_construct())
1041 std::string msg = "Cannot derive from C++ class '";
1042 msg += base->name();
1043 msg += "'. It does not have a wrapped type";
1044 lua_pushstring(L, msg.c_str());
1046 lua_error(L);
1049 #endif
1051 #ifndef LUABIND_NO_EXCEPTIONS
1056 #endif
1058 if (!rep->overloads[match_index].has_wrapped_construct())
1060 // if the type doesn't have a wrapped type, use the ordinary constructor
1061 obj->set_object(rep->overloads[match_index].construct(L));
1063 else
1065 // get reference to lua object
1066 lua_pushvalue(L, lua_upvalueindex(2));
1067 int ref = detail::ref(L);
1068 obj->set_object(rep->overloads[match_index].construct_wrapped(L, ref));
1070 // TODO: is the wrapped type destructed correctly?
1071 // it should, since the destructor is either the wrapped type's
1072 // destructor or the base type's destructor, depending on wether
1073 // the type has a wrapped type or not.
1074 obj->set_destructor(base->destructor());
1075 return 0;
1077 #ifndef LUABIND_NO_EXCEPTIONS
1080 catch(const std::exception& e)
1082 lua_pushstring(L, e.what());
1084 catch(const char* s)
1086 lua_pushstring(L, s);
1088 catch(...)
1090 std::string msg = base->m_name;
1091 msg += "() threw an exception";
1092 lua_pushstring(L, msg.c_str());
1094 // can only be reached if an exception was thrown
1095 lua_error(L);
1096 #endif
1099 return 0;
1105 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L)
1107 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1108 detail::getref(L, crep->m_table_ref);
1109 lua_replace(L, 1);
1110 lua_rawset(L, -3);
1112 crep->m_operator_cache = 0; // invalidate cache
1114 return 0;
1117 int luabind::detail::class_rep::construct_lua_class_callback(lua_State* L)
1119 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1121 int args = lua_gettop(L);
1123 // lua stack: crep <arguments>
1125 lua_newtable(L);
1126 int ref = detail::ref(L);
1128 bool has_bases = !crep->bases().empty();
1130 if (has_bases)
1132 lua_pushstring(L, "super");
1133 lua_pushvalue(L, 1); // crep
1136 // lua stack: crep <arguments> "super" crep
1137 // or
1138 // lua stack: crep <arguments>
1140 // if we have a baseclass we set the flag to say that the super has not yet been called
1141 // we will use this flag later to check that it actually was called from __init()
1142 int flags = object_rep::lua_class | object_rep::owner | (has_bases ? object_rep::call_super : 0);
1144 void* obj_ptr = lua_newuserdata(L, sizeof(object_rep));
1145 new(obj_ptr) object_rep(crep, flags, ref);
1147 detail::getref(L, crep->metatable_ref());
1148 lua_setmetatable(L, -2);
1150 // lua stack: crep <arguments> "super" crep obj_ptr
1151 // or
1152 // lua stack: crep <arguments> obj_ptr
1154 if (has_bases) lua_pushvalue(L, -1); // obj_ptr
1155 lua_replace(L, 1); // obj_ptr
1157 // lua stack: obj_ptr <arguments> "super" crep obj_ptr
1158 // or
1159 // lua stack: obj_ptr <arguments>
1161 if (has_bases)
1163 lua_pushcclosure(L, super_callback, 2);
1164 // lua stack: crep <arguments> "super" function
1165 lua_settable(L, LUA_GLOBALSINDEX);
1168 // lua stack: crep <arguments>
1170 lua_pushvalue(L, 1);
1171 lua_insert(L, 1);
1173 detail::getref(L, crep->table_ref());
1174 lua_pushstring(L, "__init");
1175 lua_gettable(L, -2);
1177 #ifndef LUABIND_NO_ERROR_CHECKING
1179 // TODO: should this be a run-time error?
1180 // maybe the default behavior should be to just call
1181 // the base calss' constructor. We should register
1182 // the super callback funktion as __init
1183 if (!lua_isfunction(L, -1))
1186 std::string msg = crep->name();
1187 msg += ":__init is not defined";
1188 lua_pushstring(L, msg.c_str());
1190 lua_error(L);
1193 #endif
1195 lua_insert(L, 2); // function first on stack
1196 lua_pop(L, 1);
1197 // TODO: lua_call may invoke longjump! make sure we don't have any memory leaks!
1198 // we don't have any stack objects here
1199 lua_call(L, args, 0);
1201 #ifndef LUABIND_NO_ERROR_CHECKING
1203 object_rep* obj = static_cast<object_rep*>(obj_ptr);
1204 if (obj->flags() & object_rep::call_super)
1206 lua_pushstring(L, "derived class must call super on base");
1207 lua_error(L);
1210 #endif
1212 return 1;
1215 // called from the metamethod for __index
1216 // obj is the object pointer
1217 int luabind::detail::class_rep::lua_class_gettable(lua_State* L)
1219 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1220 class_rep* crep = obj->crep();
1222 #ifndef LUABIND_NO_ERROR_CHECKING
1224 if (obj->flags() & object_rep::call_super)
1226 lua_pushstring(L, "derived class must call super on base");
1227 lua_error(L);
1230 #endif
1232 // we have to ignore the first argument since this may point to
1233 // a method that is not present in this class (but in a subclass)
1234 const char* key = lua_tostring(L, 2);
1236 if (key && !std::strcmp(key, "__ok"))
1238 class_rep* crep = obj->crep();
1240 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
1241 : obj->ptr();
1243 lua_pushboolean(L, p != 0);
1244 return 1;
1247 detail::getref(L, obj->lua_table_ref());
1248 lua_pushvalue(L, 2);
1249 lua_gettable(L, -2);
1251 if (!lua_isnil(L, -1))
1253 lua_remove(L, -2); // remove table
1254 return 1;
1257 lua_pop(L, 2);
1259 detail::getref(L, crep->table_ref());
1260 lua_pushvalue(L, 2);
1261 lua_gettable(L, -2);
1263 if (!lua_isnil(L, -1))
1265 lua_remove(L, -2); // more table
1266 return 1;
1269 lua_pop(L, 2);
1271 if (lua_isnil(L, 2))
1273 lua_pushnil(L);
1274 return 1;
1277 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1278 if (i != crep->m_methods.end())
1280 // the name is a method, return it
1281 lua_pushlightuserdata(L, &i->second);
1282 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1283 return 1;
1286 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_getters.find(key);
1287 if (j != crep->m_getters.end())
1289 // the name is a data member
1290 return j->second.func(L, j->second.pointer_offset);
1293 lua_pushnil(L);
1294 return 1;
1297 // called from the metamethod for __newindex
1298 // obj is the object pointer
1299 int luabind::detail::class_rep::lua_class_settable(lua_State* L)
1301 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1302 class_rep* crep = obj->crep();
1304 #ifndef LUABIND_NO_ERROR_CHECKING
1306 if (obj->flags() & object_rep::call_super)
1308 // this block makes sure the std::string is destructed
1309 // before lua_error is called
1311 std::string msg = "derived class '";
1312 msg += crep->name();
1313 msg += "'must call super on base";
1314 lua_pushstring(L, msg.c_str());
1316 lua_error(L);
1319 #endif
1321 // we have to ignore the first argument since this may point to
1322 // a method that is not present in this class (but in a subclass)
1323 const char* key = lua_tostring(L, 2);
1324 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_setters.find(key);
1326 if (j == crep->m_setters.end())
1328 std::map<const char*, class_rep::callback, ltstr>::iterator k = crep->m_getters.find(key);
1330 #ifndef LUABIND_NO_ERROR_CHECKING
1332 if (k != crep->m_getters.end())
1335 std::string msg = "cannot set property '";
1336 msg += crep->name();
1337 msg += ".";
1338 msg += key;
1339 msg += "', because it's read only";
1340 lua_pushstring(L, msg.c_str());
1342 lua_error(L);
1345 #endif
1347 detail::getref(L, obj->lua_table_ref());
1348 lua_replace(L, 1);
1349 lua_settable(L, 1);
1351 else
1353 // the name is a data member
1354 j->second.func(L, j->second.pointer_offset);
1357 return 0;
1360 int luabind::detail::class_rep::static_class_gettable(lua_State* L)
1362 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1364 // this has changed! c++ classes now also store their methods in the table
1365 // if (crep->get_class_type() == class_rep::lua_class)
1367 detail::getref(L, crep->m_table_ref);
1368 lua_pushvalue(L, 2);
1369 lua_gettable(L, -2);
1370 if (!lua_isnil(L, -1)) return 1;
1371 else lua_pop(L, 2);
1374 const char* key = lua_tostring(L, 2);
1376 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1377 if (i != crep->m_methods.end())
1379 // the name is a method, return it
1380 lua_pushlightuserdata(L, &i->second);
1381 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1382 return 1;
1385 #ifndef LUABIND_NO_ERROR_CHECKING
1387 std::map<const char*, int, ltstr>::const_iterator j = crep->m_static_constants.find(key);
1389 if (j != crep->m_static_constants.end())
1391 lua_pushnumber(L, j->second);
1392 return 1;
1396 std::string msg = "no static '";
1397 msg += key;
1398 msg += "' in class '";
1399 msg += crep->name();
1400 msg += "'";
1401 lua_pushstring(L, msg.c_str());
1403 lua_error(L);
1405 #endif
1407 return 0;
1410 bool luabind::detail::is_class_rep(lua_State* L, int index)
1412 if (lua_getmetatable(L, index) == 0) return false;
1414 lua_pushstring(L, "__luabind_classrep");
1415 lua_gettable(L, -2);
1416 if (lua_toboolean(L, -1))
1418 lua_pop(L, 2);
1419 return true;
1422 lua_pop(L, 2);
1423 return false;
1426 void luabind::detail::finalize(lua_State* L, class_rep* crep)
1428 if (crep->get_class_type() != class_rep::lua_class) return;
1430 // lua_pushvalue(L, -1); // copy the object ref
1431 detail::getref(L, crep->table_ref());
1432 lua_pushstring(L, "__finalize");
1433 lua_gettable(L, -2);
1434 lua_remove(L, -2);
1436 if (lua_isnil(L, -1))
1438 lua_pop(L, 1);
1440 else
1442 lua_pushvalue(L, -2);
1443 lua_call(L, 1, 0);
1446 for (std::vector<class_rep::base_info>::const_iterator
1447 i = crep->bases().begin(); i != crep->bases().end(); ++i)
1449 if (i->base) finalize(L, i->base);
1453 void* luabind::detail::class_rep::convert_to(LUABIND_TYPE_INFO target_type, const object_rep* obj, void* target_memory) const
1455 // TODO: since this is a member function, we don't have to use the accesor functions for
1456 // the types and the extractor
1458 int steps = 0;
1459 int offset = 0;
1460 if (!(LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), target_type))
1461 && !(LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), target_type)))
1463 steps = implicit_cast(this, target_type, offset);
1466 // should never be called with a type that can't be cast
1467 assert((steps >= 0) && "internal error, please report");
1469 if (LUABIND_TYPE_INFO_EQUAL(target_type, holder_type()))
1471 // if the type we are trying to convert to is the holder_type
1472 // it means that his crep has a holder_type (since it would have
1473 // been invalid otherwise, and T cannot be invalid). It also means
1474 // that we need no conversion, since the holder_type is what the
1475 // object points to.
1476 return obj->ptr();
1479 if (LUABIND_TYPE_INFO_EQUAL(target_type, const_holder_type()))
1481 if (obj->flags() & object_rep::constant)
1483 // we are holding a constant
1484 return obj->ptr();
1486 else
1488 // we are holding a non-constant, we need to convert it
1489 // to a const_holder.
1490 m_const_converter(obj->ptr(), target_memory);
1491 return target_memory;
1495 void* raw_pointer;
1497 if (has_holder())
1499 // this means that we have a holder type where the
1500 // raw-pointer needs to be extracted
1501 raw_pointer = extractor()(obj->ptr());
1503 else
1505 raw_pointer = obj->ptr();
1508 return static_cast<char*>(raw_pointer) + offset;
1511 void luabind::detail::class_rep::cache_operators(lua_State* L)
1513 m_operator_cache = 0x1;
1515 for (int i = 0; i < number_of_operators; ++i)
1517 getref(L, table_ref());
1518 lua_pushstring(L, get_operator_name(i));
1519 lua_rawget(L, -2);
1521 if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1);
1523 lua_pop(L, 2);
1527 bool luabind::detail::class_rep::has_operator_in_lua(lua_State* L, int id)
1529 if ((m_operator_cache & 0x1) == 0)
1530 cache_operators(L);
1532 const int mask = 1 << (id + 1);
1534 return (m_operator_cache & mask) != 0;
1537 void luabind::detail::class_rep::add_method(lua_State* L, const char* name, detail::method_rep& m)
1539 detail::getref(L, table_ref());
1540 lua_pushstring(L, name);
1541 lua_gettable(L, -2);
1543 if (lua_isnil(L, -1) || !lua_iscfunction(L, -1))
1545 lua_pop(L, 1);
1546 lua_pushstring(L, name);
1547 lua_pushlightuserdata(L, const_cast<void*>((const void*)&m));
1548 lua_pushcclosure(L, function_dispatcher, 1);
1549 lua_settable(L, -3);
1550 lua_pop(L, 1);
1552 else
1554 lua_getupvalue(L, -1, 1);
1555 method_rep* inherited = static_cast<method_rep*>(lua_touserdata(L, -1));
1557 for (std::vector<overload_rep>::const_iterator i = inherited->overloads().begin();
1558 i != inherited->overloads().end(); ++i)
1560 m.add_overload(*i);
1563 detail::getref(L, table_ref());
1564 lua_pushstring(L, name);
1565 lua_pushlightuserdata(L, const_cast<void*>((const void*)&m));
1566 lua_pushcclosure(L, function_dispatcher, 1);
1567 lua_settable(L, -3);
1568 lua_pop(L, 4);
1572 const class_rep::property_map& luabind::detail::class_rep::properties() const
1574 return m_getters;