*** empty log message ***
[luabind.git] / src / class_rep.cpp
blobfacd9e1de2b1d407bd6bc90b6e9e9718ac0f3157
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 , int holder_size
65 , int holder_alignment)
67 : m_type(type)
68 , m_holder_type(holder_type)
69 , m_const_holder_type(const_holder_type)
70 , m_extractor(extractor)
71 , m_const_extractor(const_extractor)
72 , m_const_converter(const_converter)
73 , m_construct_holder(construct_holder)
74 , m_construct_const_holder(construct_const_holder)
75 , m_holder_size(holder_size)
76 , m_holder_alignment(holder_alignment)
77 , m_name(name)
78 , m_table_ref(LUA_NOREF)
79 , m_class_type(cpp_class)
80 , m_destructor(destructor)
81 , m_const_holder_destructor(const_holder_destructor)
82 , m_operator_cache(0)
84 assert(m_holder_alignment >= 1 && "internal error");
86 lua_newtable(L);
87 m_table_ref = detail::ref(L);
89 class_registry* r = class_registry::get_registry(L);
90 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
92 detail::getref(L, r->cpp_class());
93 lua_setmetatable(L, -2);
95 lua_pushvalue(L, -1); // duplicate our user data
96 m_self_ref = detail::ref(L); // pop one of them
98 m_instance_metatable = r->cpp_instance();
101 luabind::detail::class_rep::class_rep(lua_State* L, const char* name)
102 : m_type(LUABIND_INVALID_TYPE_INFO)
103 , m_holder_type(LUABIND_INVALID_TYPE_INFO)
104 , m_const_holder_type(LUABIND_INVALID_TYPE_INFO)
105 , m_extractor(0)
106 , m_const_extractor(0)
107 , m_const_converter(0)
108 , m_construct_holder(0)
109 , m_construct_const_holder(0)
110 , m_holder_size(0)
111 , m_holder_alignment(1)
112 , m_class_type(lua_class)
113 , m_destructor(0)
114 , m_const_holder_destructor(0)
115 , m_operator_cache(0)
117 #ifndef LUABIND_DONT_COPY_STRINGS
118 m_strings.push_back(detail::dup_string(name));
119 m_name = m_strings.back();
120 #else
121 m_name = name;
122 #endif
123 lua_newtable(L);
124 m_table_ref = detail::ref(L);
126 class_registry* r = class_registry::get_registry(L);
127 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
129 detail::getref(L, r->lua_class());
130 lua_setmetatable(L, -2);
131 lua_pushvalue(L, -1); // duplicate our user data
132 m_self_ref = detail::ref(L); // pop one of them
134 m_instance_metatable = r->lua_instance();
137 luabind::detail::class_rep::~class_rep()
139 #ifndef LUABIND_DONT_COPY_STRINGS
140 for (std::vector<char*>::iterator i = m_strings.begin();
141 i != m_strings.end(); ++i)
143 delete[] *i;
145 #endif
148 // leaves object on lua stack
149 std::pair<void*,void*>
150 luabind::detail::class_rep::allocate(lua_State* L) const
152 const int overlap = sizeof(object_rep)&(m_holder_alignment-1);
153 const int padding = overlap==0?0:m_holder_alignment-overlap;
154 const int size = sizeof(object_rep) + padding + m_holder_size;
156 char* mem = static_cast<char*>(lua_newuserdata(L, size));
157 char* ptr = mem + sizeof(object_rep) + padding;
159 return std::pair<void*,void*>(mem,ptr);
162 //#include <iostream>
163 // lua stack: userdata, key
164 int luabind::detail::class_rep::gettable(lua_State* L)
166 // if key is nil, return nil
167 if (lua_isnil(L, 2))
169 lua_pushnil(L);
170 return 1;
173 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
175 // we have to ignore the first argument since this may point to
176 // a method that is not present in this class (but in a subclass)
177 const char* key = lua_tostring(L, 2);
179 #ifndef LUABIND_NO_ERROR_CHECKING
181 if (std::strlen(key) != lua_strlen(L, 2))
184 std::string msg("luabind does not support "
185 "member names with extra nulls:\n");
186 msg += std::string(lua_tostring(L, 2), lua_strlen(L, 2));
187 lua_pushstring(L, msg.c_str());
189 lua_error(L);
192 #endif
194 // special case to see if this is a null-pointer
195 if (key && !std::strcmp(key, "__ok"))
197 class_rep* crep = obj->crep();
199 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
200 : obj->ptr();
202 lua_pushboolean(L, p != 0);
203 return 1;
206 detail::getref(L, obj->crep()->table_ref());
207 lua_pushvalue(L, 2);
208 lua_gettable(L, -2);
210 if (!lua_isnil(L, -1))
212 // std::cout << "method found in lua table: " << key << "\n";
213 lua_remove(L, -2); // more table
214 return 1;
217 lua_pop(L, 2);
219 std::map<const char*, method_rep, ltstr>::iterator i = m_methods.find(key);
221 if (i != m_methods.end())
223 // the name is a method, return it
224 lua_pushlightuserdata(L, &i->second);
225 lua_pushcclosure(L, function_dispatcher, 1);
226 return 1;
229 std::map<const char*, callback, ltstr>::iterator j = m_getters.find(key);
230 if (j != m_getters.end())
232 // the name is a data member
233 return j->second.func(L, j->second.pointer_offset);
236 lua_pushnil(L);
237 return 1;
240 // called from the metamethod for __newindex
241 // the object pointer is passed on the lua stack
242 // lua stack: userdata, key, value
243 bool luabind::detail::class_rep::settable(lua_State* L)
245 // if the key is 'nil' fail
246 if (lua_isnil(L, 2)) return false;
248 // we have to ignore the first argument since this may point to
249 // a method that is not present in this class (but in a subclass)
251 const char* key = lua_tostring(L, 2);
253 if (std::strlen(key) == lua_strlen(L, 2))
255 std::map<const char*, callback, ltstr>::iterator j = m_setters.find(key);
256 if (j != m_setters.end())
258 // the name is a data member
259 #ifndef LUABIND_NO_ERROR_CHECKING
260 if (j->second.match(L, 3) < 0)
262 std::string msg("the attribute '");
263 msg += m_name;
264 msg += ".";
265 msg += key;
266 msg += "' is of type: ";
267 j->second.sig(L, msg);
268 msg += "\nand does not match: (";
269 msg += stack_content_by_name(L, 3);
270 msg += ")";
271 lua_pushstring(L, msg.c_str());
272 return false;
274 #endif
275 j->second.func(L, j->second.pointer_offset);
276 return true;
279 if (m_getters.find(key) != m_getters.end())
281 // this means that we have a getter but no
282 // setter for an attribute. We will then fail
283 // because that attribute is read-only
284 std::string msg("the attribute '");
285 msg += m_name;
286 msg += ".";
287 msg += key;
288 msg += "' is read only";
289 lua_pushstring(L, msg.c_str());
290 return false;
294 // set the attribute to the object's table
295 getref(L, table_ref());
296 lua_pushvalue(L, 2);
297 lua_pushvalue(L, 3);
298 lua_settable(L, 4);
299 lua_pop(L, 3);
300 return true;
303 int class_rep::gettable_dispatcher(lua_State* L)
305 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
306 return obj->crep()->gettable(L);
309 // this is called as __newindex metamethod on every instance of this class
310 int luabind::detail::class_rep::settable_dispatcher(lua_State* L)
312 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
314 bool success = obj->crep()->settable(L);
316 #ifndef LUABIND_NO_ERROR_CHECKING
318 if (!success)
320 // class_rep::settable() will leave
321 // error message on the stack in case
322 // of failure
323 lua_error(L);
326 #endif
328 return 0;
332 int luabind::detail::class_rep::operator_dispatcher(lua_State* L)
334 int id = static_cast<int>(lua_tonumber(L, lua_upvalueindex(1)));
336 int operand_id = 0;
338 object_rep* operand[2];
339 for (int i = 0; i < 2; ++i)
340 operand[i] = detail::is_class_object(L, i + 1);
342 // we cannot compare the types here, we have to compare the pointers of the class_reps
343 // since all lua-classes have the same type (LUABIND_INVALID_TYPE_INFO)
344 if (operand[0] && operand[1])
345 if (operand[0]->crep() == operand[1]->crep()) operand[1] = 0;
347 std::vector<operator_callback>* overloads[2];
348 for (int i = 0; i < 2; ++i)
349 if (operand[i]) overloads[i] = &operand[i]->crep()->m_operators[id]; else overloads[i] = 0;
351 std::size_t num_overloads[2];
352 for (int i = 0; i < 2; ++i)
353 if (overloads[i]) num_overloads[i] = overloads[i]->size(); else num_overloads[i] = 0;
355 for (int i = 0; i < 2; ++i)
356 if (operand[i] && operand[i]->crep()->get_class_type() == class_rep::lua_class)
358 /* // if this is a lua class we have to
359 // look in its table to see if there's
360 // any overload of this operator
361 detail::getref(L, operand[i]->crep()->table_ref());
362 lua_pushstring(L, get_operator_name(id));
363 lua_rawget(L, -2);
364 // if we have tha operator, set num_overloads to 1
365 if (lua_isfunction(L, -1)) num_overloads[i] = 1;
366 lua_pop(L, 2);*/
368 if (operand[i]->crep()->has_operator_in_lua(L, id))
369 num_overloads[i] = 1;
372 bool ambiguous = false;
373 int match_index = -1;
374 int min_match = std::numeric_limits<int>::max();
376 #ifdef LUABIND_NO_ERROR_CHECKING
378 if (num_overloads[0] == 1 && num_overloads[1] == 0)
380 operand_id = 0;
381 match_index = 0;
383 else if (num_overloads[0] == 0 && num_overloads[1] == 1)
385 operand_id = 1;
386 match_index = 0;
388 else
391 #endif
393 int num_params = lua_gettop(L);
395 // have look at the right operand.
396 // if the right operand is a class and
397 // not the same class as this, we have to
398 // try to match it's operators too
399 for (int i = 0; i < 2; ++i)
401 if (num_overloads[i])
403 if (operand[i]->crep()->get_class_type() == class_rep::lua_class)
405 // if this is a lua class
406 // and num_overloads is > 0
407 // it means that it has implemented
408 // this operator. Set match_index to
409 // 0 to signal that this operand has
410 // an overload, but leave the min_match
411 // at int-max to mark it as a last fallback
412 operand_id = i;
413 if (match_index == -1) match_index = 0;
415 else if (find_best_match(
417 , &overloads[i]->front()
418 , overloads[i]->size()
419 , sizeof(operator_callback)
420 , ambiguous
421 , min_match
422 , match_index
423 , num_params))
425 operand_id = i;
431 #ifdef LUABIND_NO_ERROR_CHECKING
435 #else
437 if (match_index == -1)
440 std::string msg("no operator ");
441 msg += get_operator_symbol(id);
442 msg += " matched the arguments (";
443 msg += stack_content_by_name(L, 1);
444 msg += ")\ncandidates are:\n";
446 for (int i = 0; i < 2; ++i)
448 if (overloads[i])
450 msg += get_overload_signatures(
452 , overloads[i]->begin()
453 , overloads[i]->end()
454 , get_operator_symbol(id));
456 else
458 // if num_overloads is > 0 it would mean that this is
459 // a lua class with this operator overloaded. And if
460 // that's the case, it should always match (and if an
461 // operator matches, we never come here).
462 assert(num_overloads[i] == 0 && "internal error");
465 lua_pushstring(L, msg.c_str());
467 lua_error(L);
469 else if (ambiguous)
472 std::string msg("call of overloaded operator ");
473 msg += get_operator_symbol(id);
474 msg += " (";
475 msg += stack_content_by_name(L, 1);
476 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
478 std::vector<const overload_rep_base*> candidates;
479 if (overloads[0])
480 find_exact_match(L, &overloads[0]->front(), overloads[0]->size(), sizeof(operator_callback), min_match, num_params, candidates);
482 if (overloads[1])
483 find_exact_match(L, &overloads[1]->front(), overloads[1]->size(), sizeof(operator_callback), min_match, num_params, candidates);
485 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), get_operator_symbol(id));
487 lua_pushstring(L, msg.c_str());
489 lua_error(L);
492 #endif
494 if (operand[operand_id]->crep()->get_class_type() == class_rep::lua_class)
496 detail::getref(L, operand[operand_id]->crep()->table_ref());
497 lua_pushstring(L, get_operator_name(id));
498 lua_rawget(L, -2);
499 lua_insert(L, -4); // move the function to the bottom
500 lua_pop(L, 1); // remove the table
501 lua_call(L, 2, 1);
502 return 1;
504 else
506 return (*overloads[operand_id])[match_index].call(L);
510 // this is called as metamethod __call on the class_rep.
511 int luabind::detail::class_rep::constructor_dispatcher(lua_State* L)
513 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
514 construct_rep* rep = &crep->m_constructor;
516 bool ambiguous = false;
517 int match_index = -1;
518 int min_match = std::numeric_limits<int>::max();
519 bool found;
521 #ifdef LUABIND_NO_ERROR_CHECKING
523 if (rep->overloads.size() == 1)
525 match_index = 0;
527 else
530 #endif
532 int num_params = lua_gettop(L) - 1;
533 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
535 #ifdef LUABIND_NO_ERROR_CHECKING
538 #else
540 if (!found)
543 std::string msg("no constructor of '");
544 msg += crep->name();
545 msg += "' matched the arguments (";
546 msg += stack_content_by_name(L, 2);
547 msg += ")\n candidates are:\n";
549 msg += get_overload_signatures(L, rep->overloads.begin(), rep->overloads.end(), crep->name());
551 lua_pushstring(L, msg.c_str());
553 lua_error(L);
555 else if (ambiguous)
558 std::string msg("call of overloaded constructor '");
559 msg += crep->m_name;
560 msg += "(";
561 msg += stack_content_by_name(L, 2);
562 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
564 std::vector<const overload_rep_base*> candidates;
565 find_exact_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), min_match, num_params, candidates);
566 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), crep->name());
568 lua_pushstring(L, msg.c_str());
570 lua_error(L);
573 #endif
575 #ifndef LUABIND_NO_EXCEPTIONS
580 #endif
582 void* object_ptr = rep->overloads[match_index].construct(L);
584 void* obj_rep;
585 void* held;
587 boost::tie(obj_rep,held) = crep->allocate(L);
589 if (crep->has_holder())
591 crep->m_construct_holder(held, object_ptr);
592 object_ptr = held;
594 new(obj_rep) object_rep(object_ptr, crep, object_rep::owner, crep->destructor());
596 detail::getref(L, crep->m_instance_metatable);
597 lua_setmetatable(L, -2);
598 return 1;
600 #ifndef LUABIND_NO_EXCEPTIONS
604 catch(const std::exception& e)
606 lua_pushstring(L, e.what());
608 catch(const char* s)
610 lua_pushstring(L, s);
612 catch(...)
615 std::string msg = crep->name();
616 msg += "() threw an exception";
617 lua_pushstring(L, msg.c_str());
621 // we can only reach this line if an exception was thrown
622 lua_error(L);
623 return 0; // will never be reached
625 #endif
629 // the functions dispatcher assumes the following:
630 // there is one upvalue that points to the method_rep that this dispatcher is to call
631 // the first parameter on the lua stack is an object_rep that points to the object the
632 // call is being made on
633 int luabind::detail::class_rep::function_dispatcher(lua_State* L)
635 method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
636 object_rep* obj = reinterpret_cast<object_rep*>(lua_touserdata(L, 1));
638 #ifndef LUABIND_NO_ERROR_CHECKING
640 if (is_class_object(L, 1) == 0)
643 std::string msg = "No self reference given as first parameter to member function '";
644 msg += rep->crep->name();
645 msg += ":";
646 msg += rep->name;
647 msg += "'. Have you used '.' instead of ':'?";
649 lua_pushstring(L, msg.c_str());
651 lua_error(L);
654 int p;
655 if (implicit_cast(obj->crep(), rep->crep->type(), p) < 0)
658 std::string msg = "invalid self reference given to '";
659 msg += rep->crep->name();
660 msg += ":";
661 msg += rep->name;
662 msg += "'";
663 lua_pushstring(L, msg.c_str());
665 lua_error(L);
668 #endif
670 bool ambiguous = false;
671 int match_index = -1;
672 int min_match = std::numeric_limits<int>::max();
673 bool found;
675 #ifdef LUABIND_NO_ERROR_CHECKING
676 if (rep->overloads().size() == 1)
678 match_index = 0;
680 else
682 #endif
684 int num_params = lua_gettop(L) - 1;
685 found = find_best_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), ambiguous, min_match, match_index, num_params);
687 #ifdef LUABIND_NO_ERROR_CHECKING
691 #else
693 if (!found)
696 std::string msg = "no overload of '";
697 msg += rep->crep->name();
698 msg += ":";
699 msg += rep->name;
700 msg += "' matched the arguments (";
701 msg += stack_content_by_name(L, 2);
702 msg += ")\ncandidates are:\n";
704 std::string function_name;
705 function_name += rep->crep->name();
706 function_name += ":";
707 function_name += rep->name;
709 msg += get_overload_signatures(L, rep->overloads().begin(), rep->overloads().end(), function_name);
711 lua_pushstring(L, msg.c_str());
713 lua_error(L);
715 else if (ambiguous)
718 std::string msg = "call of overloaded '";
719 msg += rep->crep->name();
720 msg += ":";
721 msg += rep->name;
722 msg += "(";
723 msg += stack_content_by_name(L, 2);
724 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
726 std::vector<const overload_rep_base*> candidates;
727 find_exact_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), min_match, num_params, candidates);
729 std::string function_name;
730 function_name += rep->crep->name();
731 function_name += ":";
732 function_name += rep->name;
734 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), function_name);
736 lua_pushstring(L, msg.c_str());
738 lua_error(L);
741 #endif
743 #ifndef LUABIND_NO_EXCEPTIONS
748 #endif
750 const overload_rep& o = rep->overloads()[match_index];
751 return o.call(L, *obj);
753 #ifndef LUABIND_NO_EXCEPTIONS
756 catch(const std::exception& e)
758 lua_pushstring(L, e.what());
760 catch (const char* s)
762 lua_pushstring(L, s);
764 catch(...)
766 std::string msg = rep->crep->name();
767 msg += ":";
768 msg += rep->name;
769 msg += "() threw an exception";
770 lua_pushstring(L, msg.c_str());
772 // we can only reach this line if an exception was thrown
773 lua_error(L);
774 return 0; // will never be reached
776 #endif
780 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo)
782 // If you hit this assert you are deriving from a type that is not registered
783 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
784 // Please note that if you don't need to have access to the base class or the
785 // conversion from the derived class to the base class, you don't need
786 // to tell luabind that it derives.
787 assert(binfo.base && "You cannot derive from an unregistered type");
789 class_rep* bcrep = binfo.base;
791 // import all functions from the base
792 for (std::map<const char*, method_rep, ltstr>::const_iterator i = bcrep->m_methods.begin();
793 i != bcrep->m_methods.end(); ++i)
795 // If we would assume that our base class will not be garbage collected until
796 // this class is collected, we wouldn't had to copy these strings.
797 #ifndef LUABIND_DONT_COPY_STRINGS
798 m_strings.push_back(dup_string(i->first));
799 method_rep& m = m_methods[m_strings.back()];
800 #else
801 method_rep& m = m_methods[i->first];
802 #endif
803 m.name = i->first;
804 m.crep = this;
806 for (std::vector<overload_rep>::const_iterator j = i->second.overloads().begin();
807 j != i->second.overloads().end(); ++j)
809 overload_rep o = *j;
810 o.add_offset(binfo.pointer_offset);
811 m.add_overload(o);
815 // import all getters from the base
816 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_getters.begin();
817 i != bcrep->m_getters.end(); ++i)
819 #ifndef LUABIND_DONT_COPY_STRINGS
820 m_strings.push_back(dup_string(i->first));
821 callback& m = m_getters[m_strings.back()];
822 #else
823 callback& m = m_getters[i->first];
824 #endif
825 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
826 m.func = i->second.func;
829 // import all setters from the base
830 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_setters.begin();
831 i != bcrep->m_setters.end(); ++i)
833 #ifndef LUABIND_DONT_COPY_STRINGS
834 // TODO: optimize this by not copying the string if it already exists in m_setters.
835 // This goes for m_getters, m_static_constants and m_functions too. Both here
836 // in add_base() and in the add_function(), add_getter() ... functions.
837 m_strings.push_back(dup_string(i->first));
838 callback& m = m_setters[m_strings.back()];
839 #else
840 callback& m = m_setters[i->first];
841 #endif
842 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
843 m.func = i->second.func;
846 // import all static constants
847 for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin();
848 i != bcrep->m_static_constants.end(); ++i)
850 #ifndef LUABIND_DONT_COPY_STRINGS
851 m_strings.push_back(dup_string(i->first));
852 int& v = m_static_constants[m_strings.back()];
853 #else
854 int& v = m_static_constants[i->first];
855 #endif
856 v = i->second;
859 // import all operators
860 for (int i = 0; i < number_of_operators; ++i)
862 for (std::vector<operator_callback>::const_iterator j = bcrep->m_operators[i].begin();
863 j != bcrep->m_operators[i].end(); ++j)
864 m_operators[i].push_back(*j);
867 // also, save the baseclass info to be used for typecasts
868 m_bases.push_back(binfo);
871 void luabind::detail::class_rep::add_function(const char* name, const overload_rep& o)
874 #ifdef LUABIND_DONT_COPY_STRINGS
875 detail::method_rep& method = m_methods[name];
876 method.name = name;
877 #else
878 m_strings.push_back(dup_string(name));
879 detail::method_rep& method = m_methods[m_strings.back()];
880 method.name = m_strings.back();
881 #endif
883 method.add_overload(o);
884 method.crep = this;
887 void luabind::detail::class_rep::add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
889 callback c;
890 c.func = g;
891 c.pointer_offset = 0;
892 #ifndef LUABIND_DONT_COPY_STRINGS
893 m_strings.push_back(dup_string(name));
894 m_getters[m_strings.back()] = c;
895 #else
896 m_getters[name] = c;
897 #endif
900 void luabind::detail::class_rep::add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
902 callback c;
903 c.func = s;
904 c.pointer_offset = 0;
905 #ifndef LUABIND_DONT_COPY_STRINGS
906 m_strings.push_back(dup_string(name));
907 m_setters[m_strings.back()] = c;
908 #else
909 m_setters[name] = c;
910 #endif
913 #ifndef LUABIND_NO_ERROR_CHECKING
914 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)
915 #else
916 void luabind::detail::class_rep::add_operator(lua_State*, int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
917 #endif
919 operator_callback o;
920 o.set_fun(func);
921 o.set_match_fun(matcher);
922 o.set_arity(arity);
924 #ifndef LUABIND_NO_ERROR_CHECKING
926 o.set_sig_fun(sig);
928 #endif
929 m_operators[op_id].push_back(o);
932 void luabind::detail::class_rep::add_static_constant(const char* name, int val)
934 #ifndef LUABIND_DONT_COPY_STRINGS
935 m_strings.push_back(dup_string(name));
936 m_static_constants[m_strings.back()] = val;
937 #else
938 m_static_constants[name] = val;
939 #endif
942 int luabind::detail::class_rep::super_callback(lua_State* L)
944 int args = lua_gettop(L);
946 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, lua_upvalueindex(2)));
947 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
948 class_rep* base = crep->bases()[0].base;
950 if (base->get_class_type() == class_rep::lua_class)
952 if (base->bases().empty())
954 obj->set_flags(obj->flags() & ~object_rep::call_super);
956 lua_pushstring(L, "super");
957 lua_pushnil(L);
958 lua_settable(L, LUA_GLOBALSINDEX);
960 else
962 lua_pushstring(L, "super");
963 lua_pushlightuserdata(L, base);
964 lua_pushvalue(L, lua_upvalueindex(2));
965 lua_pushcclosure(L, super_callback, 2);
966 lua_settable(L, LUA_GLOBALSINDEX);
969 detail::getref(L, base->table_ref());
970 lua_pushstring(L, "__init");
971 lua_gettable(L, -2);
972 lua_insert(L, 1);
973 lua_pop(L, 1);
975 lua_pushvalue(L, lua_upvalueindex(2));
976 lua_insert(L, 2);
978 lua_call(L, args + 1, 0);
980 // TODO: instead of clearing the global variable "super"
981 // store it temporarily in the registry. maybe we should
982 // have some kind of warning if the super global is used?
983 lua_pushstring(L, "super");
984 lua_pushnil(L);
985 lua_settable(L, LUA_GLOBALSINDEX);
987 else
989 obj->set_flags(obj->flags() & ~object_rep::call_super);
991 // we need to push some garbage at index 1 to make the construction work
992 lua_pushboolean(L, 1);
993 lua_insert(L, 1);
995 construct_rep* rep = &base->m_constructor;
997 bool ambiguous = false;
998 int match_index = -1;
999 int min_match = std::numeric_limits<int>::max();
1000 bool found;
1002 #ifdef LUABIND_NO_ERROR_CHECKING
1004 if (rep->overloads.size() == 1)
1006 match_index = 0;
1008 else
1011 #endif
1013 int num_params = lua_gettop(L) - 1;
1014 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
1016 #ifdef LUABIND_NO_ERROR_CHECKING
1020 #else
1022 if (!found)
1025 std::string msg = "no constructor of '";
1026 msg += base->m_name;
1027 msg += "' matched the arguments (";
1028 msg += stack_content_by_name(L, 2);
1029 msg += ")";
1030 lua_pushstring(L, msg.c_str());
1032 lua_error(L);
1034 else if (ambiguous)
1037 std::string msg = "call of overloaded constructor '";
1038 msg += base->m_name;
1039 msg += "(";
1040 msg += stack_content_by_name(L, 2);
1041 msg += ")' is ambiguous";
1042 lua_pushstring(L, msg.c_str());
1044 lua_error(L);
1047 // TODO: should this be a warning or something?
1049 // since the derived class is a lua class
1050 // it may have reimplemented virtual functions
1051 // therefore, we have to instantiate the Basewrapper
1052 // if there is no basewrapper, throw a run-time error
1053 if (!rep->overloads[match_index].has_wrapped_construct())
1056 std::string msg = "Cannot derive from C++ class '";
1057 msg += base->name();
1058 msg += "'. It does not have a wrapped type";
1059 lua_pushstring(L, msg.c_str());
1061 lua_error(L);
1064 #endif
1066 #ifndef LUABIND_NO_EXCEPTIONS
1071 #endif
1072 void* storage_ptr = obj->ptr();
1074 if (!rep->overloads[match_index].has_wrapped_construct())
1076 // if the type doesn't have a wrapped type, use the ordinary constructor
1077 void* instance = rep->overloads[match_index].construct(L);
1079 if (crep->has_holder())
1081 crep->m_construct_holder(storage_ptr, instance);
1083 else
1085 obj->set_object(instance);
1088 else
1090 // get reference to lua object
1091 lua_pushvalue(L, lua_upvalueindex(2));
1092 detail::lua_reference ref;
1093 ref.set(L);
1094 void* instance = rep->overloads[match_index].construct_wrapped(L, ref);
1096 if (crep->has_holder())
1098 crep->m_construct_holder(storage_ptr, instance);
1100 else
1102 obj->set_object(instance);
1105 // TODO: is the wrapped type destructed correctly?
1106 // it should, since the destructor is either the wrapped type's
1107 // destructor or the base type's destructor, depending on wether
1108 // the type has a wrapped type or not.
1109 obj->set_destructor(base->destructor());
1110 return 0;
1112 #ifndef LUABIND_NO_EXCEPTIONS
1115 catch(const std::exception& e)
1117 lua_pushstring(L, e.what());
1119 catch(const char* s)
1121 lua_pushstring(L, s);
1123 catch(...)
1125 std::string msg = base->m_name;
1126 msg += "() threw an exception";
1127 lua_pushstring(L, msg.c_str());
1129 // can only be reached if an exception was thrown
1130 lua_error(L);
1131 #endif
1134 return 0;
1140 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L)
1142 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1143 detail::getref(L, crep->m_table_ref);
1144 lua_replace(L, 1);
1145 lua_rawset(L, -3);
1147 crep->m_operator_cache = 0; // invalidate cache
1149 return 0;
1152 int luabind::detail::class_rep::construct_lua_class_callback(lua_State* L)
1154 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1156 int args = lua_gettop(L);
1158 // lua stack: crep <arguments>
1160 lua_newtable(L);
1161 detail::lua_reference ref;
1162 ref.set(L);
1164 bool has_bases = !crep->bases().empty();
1166 if (has_bases)
1168 lua_pushstring(L, "super");
1169 lua_pushvalue(L, 1); // crep
1172 // lua stack: crep <arguments> "super" crep
1173 // or
1174 // lua stack: crep <arguments>
1176 // if we have a baseclass we set the flag to say that the super has not yet been called
1177 // we will use this flag later to check that it actually was called from __init()
1178 int flags = object_rep::lua_class | object_rep::owner | (has_bases ? object_rep::call_super : 0);
1180 // void* obj_ptr = lua_newuserdata(L, sizeof(object_rep));
1181 void* obj_ptr;
1182 void* held_storage;
1184 boost::tie(obj_ptr, held_storage) = crep->allocate(L);
1185 (new(obj_ptr) object_rep(crep, flags, ref))->set_object(held_storage);
1187 detail::getref(L, crep->metatable_ref());
1188 lua_setmetatable(L, -2);
1190 // lua stack: crep <arguments> "super" crep obj_ptr
1191 // or
1192 // lua stack: crep <arguments> obj_ptr
1194 if (has_bases) lua_pushvalue(L, -1); // obj_ptr
1195 lua_replace(L, 1); // obj_ptr
1197 // lua stack: obj_ptr <arguments> "super" crep obj_ptr
1198 // or
1199 // lua stack: obj_ptr <arguments>
1201 if (has_bases)
1203 lua_pushcclosure(L, super_callback, 2);
1204 // lua stack: crep <arguments> "super" function
1205 lua_settable(L, LUA_GLOBALSINDEX);
1208 // lua stack: crep <arguments>
1210 lua_pushvalue(L, 1);
1211 lua_insert(L, 1);
1213 detail::getref(L, crep->table_ref());
1214 lua_pushstring(L, "__init");
1215 lua_gettable(L, -2);
1217 #ifndef LUABIND_NO_ERROR_CHECKING
1219 // TODO: should this be a run-time error?
1220 // maybe the default behavior should be to just call
1221 // the base calss' constructor. We should register
1222 // the super callback funktion as __init
1223 if (!lua_isfunction(L, -1))
1226 std::string msg = crep->name();
1227 msg += ":__init is not defined";
1228 lua_pushstring(L, msg.c_str());
1230 lua_error(L);
1233 #endif
1235 lua_insert(L, 2); // function first on stack
1236 lua_pop(L, 1);
1237 // TODO: lua_call may invoke longjump! make sure we don't have any memory leaks!
1238 // we don't have any stack objects here
1239 lua_call(L, args, 0);
1241 #ifndef LUABIND_NO_ERROR_CHECKING
1243 object_rep* obj = static_cast<object_rep*>(obj_ptr);
1244 if (obj->flags() & object_rep::call_super)
1246 lua_pushstring(L, "derived class must call super on base");
1247 lua_error(L);
1250 #endif
1252 return 1;
1255 // called from the metamethod for __index
1256 // obj is the object pointer
1257 int luabind::detail::class_rep::lua_class_gettable(lua_State* L)
1259 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1260 class_rep* crep = obj->crep();
1262 #ifndef LUABIND_NO_ERROR_CHECKING
1264 if (obj->flags() & object_rep::call_super)
1266 lua_pushstring(L, "derived class must call super on base");
1267 lua_error(L);
1270 #endif
1272 // we have to ignore the first argument since this may point to
1273 // a method that is not present in this class (but in a subclass)
1275 // BUG: This might catch members called "__ok\0foobar"
1276 const char* key = lua_tostring(L, 2);
1278 if (key && !std::strcmp(key, "__ok"))
1280 class_rep* crep = obj->crep();
1282 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
1283 : obj->ptr();
1285 lua_pushboolean(L, p != 0);
1286 return 1;
1289 obj->get_lua_table(L);
1290 lua_pushvalue(L, 2);
1291 lua_gettable(L, -2);
1293 if (!lua_isnil(L, -1))
1295 lua_remove(L, -2); // remove table
1296 return 1;
1299 lua_pop(L, 2);
1301 detail::getref(L, crep->table_ref());
1302 lua_pushvalue(L, 2);
1303 lua_gettable(L, -2);
1305 if (!lua_isnil(L, -1))
1307 lua_remove(L, -2); // more table
1308 return 1;
1311 lua_pop(L, 2);
1313 if (lua_isnil(L, 2))
1315 lua_pushnil(L);
1316 return 1;
1319 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1320 if (i != crep->m_methods.end())
1322 // the name is a method, return it
1323 lua_pushlightuserdata(L, &i->second);
1324 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1325 return 1;
1328 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_getters.find(key);
1329 if (j != crep->m_getters.end())
1331 // the name is a data member
1332 return j->second.func(L, j->second.pointer_offset);
1335 lua_pushnil(L);
1336 return 1;
1339 // called from the metamethod for __newindex
1340 // obj is the object pointer
1341 int luabind::detail::class_rep::lua_class_settable(lua_State* L)
1343 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1344 class_rep* crep = obj->crep();
1346 #ifndef LUABIND_NO_ERROR_CHECKING
1348 if (obj->flags() & object_rep::call_super)
1350 // this block makes sure the std::string is destructed
1351 // before lua_error is called
1353 std::string msg = "derived class '";
1354 msg += crep->name();
1355 msg += "'must call super on base";
1356 lua_pushstring(L, msg.c_str());
1358 lua_error(L);
1361 #endif
1363 // we have to ignore the first argument since this may point to
1364 // a method that is not present in this class (but in a subclass)
1365 // BUG: This will not work with keys with extra nulls in them
1366 const char* key = lua_tostring(L, 2);
1369 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_setters.find(key);
1371 // if the strlen(key) is not the true length,
1372 // it means that the member-name contains
1373 // extra nulls. luabind does not support such
1374 // names as member names. So, use the lua
1375 // table as fall-back
1376 if (j == crep->m_setters.end()
1377 || std::strlen(key) != lua_strlen(L, 2))
1379 std::map<const char*, class_rep::callback, ltstr>::iterator k = crep->m_getters.find(key);
1381 #ifndef LUABIND_NO_ERROR_CHECKING
1383 if (k != crep->m_getters.end())
1386 std::string msg = "cannot set property '";
1387 msg += crep->name();
1388 msg += ".";
1389 msg += key;
1390 msg += "', because it's read only";
1391 lua_pushstring(L, msg.c_str());
1393 lua_error(L);
1396 #endif
1398 obj->get_lua_table(L);
1399 lua_replace(L, 1);
1400 lua_settable(L, 1);
1402 else
1404 // the name is a data member
1405 j->second.func(L, j->second.pointer_offset);
1408 return 0;
1411 int luabind::detail::class_rep::static_class_gettable(lua_State* L)
1413 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1415 detail::getref(L, crep->m_table_ref);
1416 lua_pushvalue(L, 2);
1417 lua_gettable(L, -2);
1418 if (!lua_isnil(L, -1)) return 1;
1419 else lua_pop(L, 2);
1421 const char* key = lua_tostring(L, 2);
1423 if (std::strlen(key) != lua_strlen(L, 2))
1425 lua_pushnil(L);
1426 return 1;
1429 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1430 if (i != crep->m_methods.end())
1432 // the name is a method, return it
1433 lua_pushlightuserdata(L, &i->second);
1434 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1435 return 1;
1438 std::map<const char*, int, ltstr>::const_iterator j = crep->m_static_constants.find(key);
1440 if (j != crep->m_static_constants.end())
1442 lua_pushnumber(L, j->second);
1443 return 1;
1446 #ifndef LUABIND_NO_ERROR_CHECKING
1449 std::string msg = "no static '";
1450 msg += key;
1451 msg += "' in class '";
1452 msg += crep->name();
1453 msg += "'";
1454 lua_pushstring(L, msg.c_str());
1456 lua_error(L);
1458 #endif
1460 lua_pushnil(L);
1462 return 1;
1465 bool luabind::detail::is_class_rep(lua_State* L, int index)
1467 if (lua_getmetatable(L, index) == 0) return false;
1469 lua_pushstring(L, "__luabind_classrep");
1470 lua_gettable(L, -2);
1471 if (lua_toboolean(L, -1))
1473 lua_pop(L, 2);
1474 return true;
1477 lua_pop(L, 2);
1478 return false;
1481 void luabind::detail::finalize(lua_State* L, class_rep* crep)
1483 if (crep->get_class_type() != class_rep::lua_class) return;
1485 // lua_pushvalue(L, -1); // copy the object ref
1486 detail::getref(L, crep->table_ref());
1487 lua_pushstring(L, "__finalize");
1488 lua_gettable(L, -2);
1489 lua_remove(L, -2);
1491 if (lua_isnil(L, -1))
1493 lua_pop(L, 1);
1495 else
1497 lua_pushvalue(L, -2);
1498 lua_call(L, 1, 0);
1501 for (std::vector<class_rep::base_info>::const_iterator
1502 i = crep->bases().begin(); i != crep->bases().end(); ++i)
1504 if (i->base) finalize(L, i->base);
1508 void* luabind::detail::class_rep::convert_to(LUABIND_TYPE_INFO target_type, const object_rep* obj, void* target_memory) const
1510 // TODO: since this is a member function, we don't have to use the accesor functions for
1511 // the types and the extractor
1513 int steps = 0;
1514 int offset = 0;
1515 if (!(LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), target_type))
1516 && !(LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), target_type)))
1518 steps = implicit_cast(this, target_type, offset);
1521 // should never be called with a type that can't be cast
1522 assert((steps >= 0) && "internal error, please report");
1524 if (LUABIND_TYPE_INFO_EQUAL(target_type, holder_type()))
1526 // if the type we are trying to convert to is the holder_type
1527 // it means that his crep has a holder_type (since it would have
1528 // been invalid otherwise, and T cannot be invalid). It also means
1529 // that we need no conversion, since the holder_type is what the
1530 // object points to.
1531 return obj->ptr();
1534 if (LUABIND_TYPE_INFO_EQUAL(target_type, const_holder_type()))
1536 if (obj->flags() & object_rep::constant)
1538 // we are holding a constant
1539 return obj->ptr();
1541 else
1543 // we are holding a non-constant, we need to convert it
1544 // to a const_holder.
1545 m_const_converter(obj->ptr(), target_memory);
1546 return target_memory;
1550 void* raw_pointer;
1552 if (has_holder())
1554 // this means that we have a holder type where the
1555 // raw-pointer needs to be extracted
1556 raw_pointer = extractor()(obj->ptr());
1558 else
1560 raw_pointer = obj->ptr();
1563 return static_cast<char*>(raw_pointer) + offset;
1566 void luabind::detail::class_rep::cache_operators(lua_State* L)
1568 m_operator_cache = 0x1;
1570 for (int i = 0; i < number_of_operators; ++i)
1572 getref(L, table_ref());
1573 lua_pushstring(L, get_operator_name(i));
1574 lua_rawget(L, -2);
1576 if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1);
1578 lua_pop(L, 2);
1582 bool luabind::detail::class_rep::has_operator_in_lua(lua_State* L, int id)
1584 if ((m_operator_cache & 0x1) == 0)
1585 cache_operators(L);
1587 const int mask = 1 << (id + 1);
1589 return (m_operator_cache & mask) != 0;
1592 void luabind::detail::class_rep::add_method(lua_State* L, const char* name, detail::method_rep& m)
1594 detail::getref(L, table_ref());
1595 lua_pushstring(L, name);
1596 lua_gettable(L, -2);
1598 if (lua_isnil(L, -1) || !lua_iscfunction(L, -1))
1600 lua_pop(L, 1);
1601 lua_pushstring(L, name);
1602 lua_pushlightuserdata(L, const_cast<void*>((const void*)&m));
1603 lua_pushcclosure(L, function_dispatcher, 1);
1604 lua_settable(L, -3);
1605 lua_pop(L, 1);
1607 else
1609 lua_getupvalue(L, -1, 1);
1610 method_rep* inherited = static_cast<method_rep*>(lua_touserdata(L, -1));
1612 for (std::vector<overload_rep>::const_iterator i = inherited->overloads().begin();
1613 i != inherited->overloads().end(); ++i)
1615 m.add_overload(*i);
1618 detail::getref(L, table_ref());
1619 lua_pushstring(L, name);
1620 lua_pushlightuserdata(L, const_cast<void*>((const void*)&m));
1621 lua_pushcclosure(L, function_dispatcher, 1);
1622 lua_settable(L, -3);
1623 lua_pop(L, 4);
1627 const class_rep::property_map& luabind::detail::class_rep::properties() const
1629 return m_getters;