*** empty log message ***
[luabind.git] / src / class_rep.cpp
blob28600b9e22d2b576c6859676690daeda7bff75f4
1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
23 #include <luabind/lua_include.hpp>
25 #define LUABIND_BUILDING
27 #include <luabind/luabind.hpp>
28 #include <utility>
30 using namespace luabind::detail;
33 #ifndef LUABIND_NO_ERROR_CHECKING
35 std::string luabind::detail::get_overload_signatures_candidates(
36 lua_State* L
37 , std::vector<const overload_rep_base*>::iterator start
38 , std::vector<const overload_rep_base*>::iterator end
39 , std::string name)
41 std::string s;
42 for (; start != end; ++start)
44 s += name;
45 (*start)->get_signature(L, s);
46 s += "\n";
48 return s;
51 #endif
54 luabind::detail::class_rep::class_rep(LUABIND_TYPE_INFO type
55 , const char* name
56 , lua_State* L
57 , void(*destructor)(void*)
58 , void(*const_holder_destructor)(void*)
59 , LUABIND_TYPE_INFO holder_type
60 , LUABIND_TYPE_INFO const_holder_type
61 , void*(*extractor)(void*)
62 , const void*(*const_extractor)(void*)
63 , void(*const_converter)(void*,void*)
64 , void(*construct_holder)(void*,void*)
65 , void(*construct_const_holder)(void*,void*)
66 , int holder_size
67 , int holder_alignment)
69 : m_type(type)
70 , m_holder_type(holder_type)
71 , m_const_holder_type(const_holder_type)
72 , m_extractor(extractor)
73 , m_const_extractor(const_extractor)
74 , m_const_converter(const_converter)
75 , m_construct_holder(construct_holder)
76 , m_construct_const_holder(construct_const_holder)
77 , m_holder_size(holder_size)
78 , m_holder_alignment(holder_alignment)
79 , m_name(name)
80 , m_table_ref(LUA_NOREF)
81 , m_class_type(cpp_class)
82 , m_destructor(destructor)
83 , m_const_holder_destructor(const_holder_destructor)
84 , m_operator_cache(0)
86 assert(m_holder_alignment >= 1 && "internal error");
88 lua_newtable(L);
89 m_table_ref = detail::ref(L);
91 class_registry* r = class_registry::get_registry(L);
92 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
94 detail::getref(L, r->cpp_class());
95 lua_setmetatable(L, -2);
97 lua_pushvalue(L, -1); // duplicate our user data
98 m_self_ref = detail::ref(L); // pop one of them
100 m_instance_metatable = r->cpp_instance();
103 luabind::detail::class_rep::class_rep(lua_State* L, const char* name)
104 : m_type(LUABIND_INVALID_TYPE_INFO)
105 , m_holder_type(LUABIND_INVALID_TYPE_INFO)
106 , m_const_holder_type(LUABIND_INVALID_TYPE_INFO)
107 , m_extractor(0)
108 , m_const_extractor(0)
109 , m_const_converter(0)
110 , m_construct_holder(0)
111 , m_construct_const_holder(0)
112 , m_holder_size(0)
113 , m_holder_alignment(1)
114 , m_class_type(lua_class)
115 , m_destructor(0)
116 , m_const_holder_destructor(0)
117 , m_operator_cache(0)
119 #ifndef LUABIND_DONT_COPY_STRINGS
120 m_strings.push_back(detail::dup_string(name));
121 m_name = m_strings.back();
122 #else
123 m_name = name;
124 #endif
125 lua_newtable(L);
126 m_table_ref = detail::ref(L);
128 class_registry* r = class_registry::get_registry(L);
129 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
131 detail::getref(L, r->lua_class());
132 lua_setmetatable(L, -2);
133 lua_pushvalue(L, -1); // duplicate our user data
134 m_self_ref = detail::ref(L); // pop one of them
136 m_instance_metatable = r->lua_instance();
139 luabind::detail::class_rep::~class_rep()
141 #ifndef LUABIND_DONT_COPY_STRINGS
142 for (std::vector<char*>::iterator i = m_strings.begin();
143 i != m_strings.end(); ++i)
145 delete[] *i;
147 #endif
150 // leaves object on lua stack
151 std::pair<void*,void*>
152 luabind::detail::class_rep::allocate(lua_State* L) const
154 const int overlap = sizeof(object_rep)&(m_holder_alignment-1);
155 const int padding = overlap==0?0:m_holder_alignment-overlap;
156 const int size = sizeof(object_rep) + padding + m_holder_size;
158 char* mem = static_cast<char*>(lua_newuserdata(L, size));
159 char* ptr = mem + sizeof(object_rep) + padding;
161 return std::pair<void*,void*>(mem,ptr);
164 //#include <iostream>
165 // lua stack: userdata, key
166 int luabind::detail::class_rep::gettable(lua_State* L)
168 // if key is nil, return nil
169 if (lua_isnil(L, 2))
171 lua_pushnil(L);
172 return 1;
175 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
177 // we have to ignore the first argument since this may point to
178 // a method that is not present in this class (but in a subclass)
179 // BUG: This might catch members called "__ok\0foobar"
180 const char* key = lua_tostring(L, 2);
182 // special case to see if this is a null-pointer
183 if (key && !std::strcmp(key, "__ok"))
185 class_rep* crep = obj->crep();
187 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
188 : obj->ptr();
190 lua_pushboolean(L, p != 0);
191 return 1;
194 detail::getref(L, obj->crep()->table_ref());
195 lua_pushvalue(L, 2);
196 lua_gettable(L, -2);
198 if (!lua_isnil(L, -1))
200 // std::cout << "method found in lua table: " << key << "\n";
201 lua_remove(L, -2); // more table
202 return 1;
205 lua_pop(L, 2);
207 std::map<const char*, method_rep, ltstr>::iterator i = m_methods.find(key);
209 if (i != m_methods.end())
211 // the name is a method, return it
212 lua_pushlightuserdata(L, &i->second);
213 lua_pushcclosure(L, function_dispatcher, 1);
214 return 1;
217 std::map<const char*, callback, ltstr>::iterator j = m_getters.find(key);
218 if (j != m_getters.end())
220 // the name is a data member
221 return j->second.func(L, j->second.pointer_offset);
224 lua_pushnil(L);
225 return 1;
228 // called from the metamethod for __newindex
229 // the object pointer is passed on the lua stack
230 // lua stack: userdata, key, value
231 bool luabind::detail::class_rep::settable(lua_State* L)
233 // if the key is 'nil' fail
234 if (lua_isnil(L, 2)) return false;
236 // we have to ignore the first argument since this may point to
237 // a method that is not present in this class (but in a subclass)
239 // BUG: This will not work with keys that have extra nulls in them!
240 const char* key = lua_tostring(L, 2);
241 std::map<const char*, callback, ltstr>::iterator j = m_setters.find(key);
242 if (j != m_setters.end())
244 // the name is a data member
245 j->second.func(L, j->second.pointer_offset);
246 return true;
249 if (m_getters.find(key) != m_getters.end())
251 // this means that we have a getter but no
252 // setter for an attribute. We will then fail
253 // because that attribute is read-only
254 return false;
257 // set the attribute to the object's table
258 getref(L, table_ref());
259 lua_pushvalue(L, 2);
260 lua_pushvalue(L, 3);
261 lua_settable(L, 4);
262 lua_pop(L, 3);
263 return true;
266 int class_rep::gettable_dispatcher(lua_State* L)
268 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
269 return obj->crep()->gettable(L);
272 // this is called as __newindex metamethod on every instance of this class
273 int luabind::detail::class_rep::settable_dispatcher(lua_State* L)
275 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
277 bool success = obj->crep()->settable(L);
279 #ifndef LUABIND_NO_ERROR_CHECKING
281 if (!success)
283 // this block is needed to make sure the std::string is destructed before
284 // lua_error() is called
285 #ifdef BOOST_MSVC
287 // msvc has a bug which deletes the string twice, that's
288 // why we have to create it on the heap
289 std::string* msg = new std::string("cannot set attribute '");
290 *msg += obj->crep()->m_name;
291 *msg += ".";
292 *msg += lua_tostring(L, -2);
293 *msg += "'";
294 lua_pushstring(L, msg->c_str());
295 delete msg;
297 #else
299 std::string msg = "cannot set attribute '";
300 msg += obj->crep()->m_name;
301 msg += ".";
302 msg += lua_tostring(L, -2);
303 msg += "'";
304 lua_pushstring(L, msg.c_str());
306 #endif
307 lua_error(L);
310 #endif
312 return 0;
316 int luabind::detail::class_rep::operator_dispatcher(lua_State* L)
318 int id = static_cast<int>(lua_tonumber(L, lua_upvalueindex(1)));
320 int operand_id = 0;
322 object_rep* operand[2];
323 for (int i = 0; i < 2; ++i)
324 operand[i] = detail::is_class_object(L, i + 1);
326 // we cannot compare the types here, we have to compare the pointers of the class_reps
327 // since all lua-classes have the same type (LUABIND_INVALID_TYPE_INFO)
328 if (operand[0] && operand[1])
329 if (operand[0]->crep() == operand[1]->crep()) operand[1] = 0;
331 std::vector<operator_callback>* overloads[2];
332 for (int i = 0; i < 2; ++i)
333 if (operand[i]) overloads[i] = &operand[i]->crep()->m_operators[id]; else overloads[i] = 0;
335 std::size_t num_overloads[2];
336 for (int i = 0; i < 2; ++i)
337 if (overloads[i]) num_overloads[i] = overloads[i]->size(); else num_overloads[i] = 0;
339 for (int i = 0; i < 2; ++i)
340 if (operand[i] && operand[i]->crep()->get_class_type() == class_rep::lua_class)
342 /* // if this is a lua class we have to
343 // look in its table to see if there's
344 // any overload of this operator
345 detail::getref(L, operand[i]->crep()->table_ref());
346 lua_pushstring(L, get_operator_name(id));
347 lua_rawget(L, -2);
348 // if we have tha operator, set num_overloads to 1
349 if (lua_isfunction(L, -1)) num_overloads[i] = 1;
350 lua_pop(L, 2);*/
352 if (operand[i]->crep()->has_operator_in_lua(L, id))
353 num_overloads[i] = 1;
356 bool ambiguous = false;
357 int match_index = -1;
358 int min_match = std::numeric_limits<int>::max();
360 #ifdef LUABIND_NO_ERROR_CHECKING
362 if (num_overloads[0] == 1 && num_overloads[1] == 0)
364 operand_id = 0;
365 match_index = 0;
367 else if (num_overloads[0] == 0 && num_overloads[1] == 1)
369 operand_id = 1;
370 match_index = 0;
372 else
375 #endif
377 int num_params = lua_gettop(L);
379 // have look at the right operand.
380 // if the right operand is a class and
381 // not the same class as this, we have to
382 // try to match it's operators too
383 for (int i = 0; i < 2; ++i)
385 if (num_overloads[i])
387 if (operand[i]->crep()->get_class_type() == class_rep::lua_class)
389 // if this is a lua class
390 // and num_overloads is > 0
391 // it means that it has implemented
392 // this operator. Set match_index to
393 // 0 to signal that this operand has
394 // an overload, but leave the min_match
395 // at int-max to mark it as a last fallback
396 operand_id = i;
397 if (match_index == -1) match_index = 0;
399 else if (find_best_match(
401 , &overloads[i]->front()
402 , overloads[i]->size()
403 , sizeof(operator_callback)
404 , ambiguous
405 , min_match
406 , match_index
407 , num_params))
409 operand_id = i;
415 #ifdef LUABIND_NO_ERROR_CHECKING
419 #else
421 if (match_index == -1)
423 // this block is needed to make sure the std::string is destructed before
424 // lua_error() is called
426 std::string msg = "no operator ";
427 msg += get_operator_symbol(id);
428 msg += " matched the arguments (";
429 msg += stack_content_by_name(L, 1);
430 msg += ")\ncandidates are:\n";
432 for (int i = 0; i < 2; ++i)
434 if (overloads[i])
436 msg += get_overload_signatures(
438 , overloads[i]->begin()
439 , overloads[i]->end()
440 , get_operator_symbol(id));
442 else
444 // if num_overloads is > 0 it would mean that this is
445 // a lua class with this operator overloaded. And if
446 // that's the case, it should always match (and if an
447 // operator matches, we never come here).
448 assert(num_overloads[i] == 0 && "internal error");
452 lua_pushstring(L, msg.c_str());
454 lua_error(L);
456 else if (ambiguous)
458 // this block is needed to make sure the std::string is destructed before
459 // lua_error() is called
461 std::string msg = "call of overloaded operator ";
462 msg += get_operator_symbol(id);
463 msg += " (";
464 msg += stack_content_by_name(L, 1);
465 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
467 std::vector<const overload_rep_base*> candidates;
468 if (overloads[0])
469 find_exact_match(L, &overloads[0]->front(), overloads[0]->size(), sizeof(operator_callback), min_match, num_params, candidates);
471 if (overloads[1])
472 find_exact_match(L, &overloads[1]->front(), overloads[1]->size(), sizeof(operator_callback), min_match, num_params, candidates);
474 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), get_operator_symbol(id));
476 lua_pushstring(L, msg.c_str());
478 lua_error(L);
481 #endif
483 if (operand[operand_id]->crep()->get_class_type() == class_rep::lua_class)
485 detail::getref(L, operand[operand_id]->crep()->table_ref());
486 lua_pushstring(L, get_operator_name(id));
487 lua_rawget(L, -2);
488 lua_insert(L, -4); // move the function to the bottom
489 lua_pop(L, 1); // remove the table
490 lua_call(L, 2, 1);
491 return 1;
493 else
495 return (*overloads[operand_id])[match_index].call(L);
499 // this is called as metamethod __call on the class_rep.
500 int luabind::detail::class_rep::constructor_dispatcher(lua_State* L)
502 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
503 construct_rep* rep = &crep->m_constructor;
505 bool ambiguous = false;
506 int match_index = -1;
507 int min_match = std::numeric_limits<int>::max();
508 bool found;
510 #ifdef LUABIND_NO_ERROR_CHECKING
512 if (rep->overloads.size() == 1)
514 match_index = 0;
516 else
519 #endif
521 int num_params = lua_gettop(L) - 1;
522 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
524 #ifdef LUABIND_NO_ERROR_CHECKING
527 #else
529 if (!found)
531 // this block is needed to make sure the std::string is destructed before
532 // lua_error() is called
534 std::string msg = "no constructor of '";
535 msg += crep->name();
536 msg += "' matched the arguments (";
537 msg += stack_content_by_name(L, 2);
538 msg += ")\n candidates are:\n";
540 msg += get_overload_signatures(L, rep->overloads.begin(), rep->overloads.end(), crep->name());
542 lua_pushstring(L, msg.c_str());
544 lua_error(L);
546 else if (ambiguous)
548 // this block is needed to make sure the std::string is destructed before
549 // lua_error() is called
551 std::string msg = "call of overloaded constructor '";
552 msg += crep->m_name;
553 msg += "(";
554 msg += stack_content_by_name(L, 2);
555 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
557 std::vector<const overload_rep_base*> candidates;
558 find_exact_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), min_match, num_params, candidates);
559 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), crep->name());
561 lua_pushstring(L, msg.c_str());
563 lua_error(L);
566 #endif
568 #ifndef LUABIND_NO_EXCEPTIONS
573 #endif
575 void* object_ptr = rep->overloads[match_index].construct(L);
577 void* obj_rep;
578 void* held;
580 boost::tie(obj_rep,held) = crep->allocate(L);
582 if (crep->has_holder())
584 crep->m_construct_holder(held, object_ptr);
585 object_ptr = held;
587 new(obj_rep) object_rep(object_ptr, crep, object_rep::owner, crep->destructor());
589 detail::getref(L, crep->m_instance_metatable);
590 lua_setmetatable(L, -2);
591 return 1;
593 #ifndef LUABIND_NO_EXCEPTIONS
597 catch(const std::exception& e)
599 lua_pushstring(L, e.what());
601 catch(const char* s)
603 lua_pushstring(L, s);
605 catch(...)
608 std::string msg = crep->name();
609 msg += "() threw an exception";
610 lua_pushstring(L, msg.c_str());
614 // we can only reach this line if an exception was thrown
615 lua_error(L);
616 return 0; // will never be reached
618 #endif
622 // the functions dispatcher assumes the following:
623 // there is one upvalue that points to the method_rep that this dispatcher is to call
624 // the first parameter on the lua stack is an object_rep that points to the object the
625 // call is being made on
626 int luabind::detail::class_rep::function_dispatcher(lua_State* L)
628 method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
629 object_rep* obj = reinterpret_cast<object_rep*>(lua_touserdata(L, 1));
631 #ifndef LUABIND_NO_ERROR_CHECKING
633 if (is_class_object(L, 1) == 0)
636 std::string msg = "No self reference given as first parameter to member function '";
637 msg += rep->crep->name();
638 msg += ":";
639 msg += rep->name;
640 msg += "'. Have you used '.' instead of ':'?";
642 lua_pushstring(L, msg.c_str());
644 lua_error(L);
647 int p;
648 if (implicit_cast(obj->crep(), rep->crep->type(), p) < 0)
651 std::string msg = "invalid self reference given to '";
652 msg += rep->crep->name();
653 msg += ":";
654 msg += rep->name;
655 msg += "'";
656 lua_pushstring(L, msg.c_str());
658 lua_error(L);
661 #endif
663 bool ambiguous = false;
664 int match_index = -1;
665 int min_match = std::numeric_limits<int>::max();
666 bool found;
668 #ifdef LUABIND_NO_ERROR_CHECKING
669 if (rep->overloads().size() == 1)
671 match_index = 0;
673 else
675 #endif
677 int num_params = lua_gettop(L) - 1;
678 found = find_best_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), ambiguous, min_match, match_index, num_params);
680 #ifdef LUABIND_NO_ERROR_CHECKING
684 #else
686 if (!found)
689 std::string msg = "no overload of '";
690 msg += rep->crep->name();
691 msg += ":";
692 msg += rep->name;
693 msg += "' matched the arguments (";
694 msg += stack_content_by_name(L, 2);
695 msg += ")\ncandidates are:\n";
697 std::string function_name;
698 function_name += rep->crep->name();
699 function_name += ":";
700 function_name += rep->name;
702 msg += get_overload_signatures(L, rep->overloads().begin(), rep->overloads().end(), function_name);
704 lua_pushstring(L, msg.c_str());
706 lua_error(L);
708 else if (ambiguous)
711 std::string msg = "call of overloaded '";
712 msg += rep->crep->name();
713 msg += ":";
714 msg += rep->name;
715 msg += "(";
716 msg += stack_content_by_name(L, 2);
717 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
719 std::vector<const overload_rep_base*> candidates;
720 find_exact_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), min_match, num_params, candidates);
722 std::string function_name;
723 function_name += rep->crep->name();
724 function_name += ":";
725 function_name += rep->name;
727 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), function_name);
729 lua_pushstring(L, msg.c_str());
731 lua_error(L);
734 #endif
736 #ifndef LUABIND_NO_EXCEPTIONS
741 #endif
743 const overload_rep& o = rep->overloads()[match_index];
744 return o.call(L, *obj);
746 #ifndef LUABIND_NO_EXCEPTIONS
749 catch(const std::exception& e)
751 lua_pushstring(L, e.what());
753 catch (const char* s)
755 lua_pushstring(L, s);
757 catch(...)
759 std::string msg = rep->crep->name();
760 msg += ":";
761 msg += rep->name;
762 msg += "() threw an exception";
763 lua_pushstring(L, msg.c_str());
765 // we can only reach this line if an exception was thrown
766 lua_error(L);
767 return 0; // will never be reached
769 #endif
773 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo)
775 // If you hit this assert you are deriving from a type that is not registered
776 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
777 // Please note that if you don't need to have access to the base class or the
778 // conversion from the derived class to the base class, you don't need
779 // to tell luabind that it derives.
780 assert(binfo.base && "You cannot derive from an unregistered type");
782 class_rep* bcrep = binfo.base;
784 // import all functions from the base
785 for (std::map<const char*, method_rep, ltstr>::const_iterator i = bcrep->m_methods.begin();
786 i != bcrep->m_methods.end(); ++i)
788 // If we would assume that our base class will not be garbage collected until
789 // this class is collected, we wouldn't had to copy these strings.
790 #ifndef LUABIND_DONT_COPY_STRINGS
791 m_strings.push_back(dup_string(i->first));
792 method_rep& m = m_methods[m_strings.back()];
793 #else
794 method_rep& m = m_methods[i->first];
795 #endif
796 m.name = i->first;
797 m.crep = this;
799 for (std::vector<overload_rep>::const_iterator j = i->second.overloads().begin();
800 j != i->second.overloads().end(); ++j)
802 overload_rep o = *j;
803 o.add_offset(binfo.pointer_offset);
804 m.add_overload(o);
808 // import all getters from the base
809 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_getters.begin();
810 i != bcrep->m_getters.end(); ++i)
812 #ifndef LUABIND_DONT_COPY_STRINGS
813 m_strings.push_back(dup_string(i->first));
814 callback& m = m_getters[m_strings.back()];
815 #else
816 callback& m = m_getters[i->first];
817 #endif
818 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
819 m.func = i->second.func;
822 // import all setters from the base
823 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_setters.begin();
824 i != bcrep->m_setters.end(); ++i)
826 #ifndef LUABIND_DONT_COPY_STRINGS
827 // TODO: optimize this by not copying the string if it already exists in m_setters.
828 // This goes for m_getters, m_static_constants and m_functions too. Both here
829 // in add_base() and in the add_function(), add_getter() ... functions.
830 m_strings.push_back(dup_string(i->first));
831 callback& m = m_setters[m_strings.back()];
832 #else
833 callback& m = m_setters[i->first];
834 #endif
835 m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
836 m.func = i->second.func;
839 // import all static constants
840 for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin();
841 i != bcrep->m_static_constants.end(); ++i)
843 #ifndef LUABIND_DONT_COPY_STRINGS
844 m_strings.push_back(dup_string(i->first));
845 int& v = m_static_constants[m_strings.back()];
846 #else
847 int& v = m_static_constants[i->first];
848 #endif
849 v = i->second;
852 // import all operators
853 for (int i = 0; i < number_of_operators; ++i)
855 for (std::vector<operator_callback>::const_iterator j = bcrep->m_operators[i].begin();
856 j != bcrep->m_operators[i].end(); ++j)
857 m_operators[i].push_back(*j);
860 // also, save the baseclass info to be used for typecasts
861 m_bases.push_back(binfo);
864 void luabind::detail::class_rep::add_function(const char* name, const overload_rep& o)
867 #ifdef LUABIND_DONT_COPY_STRINGS
868 detail::method_rep& method = m_methods[name];
869 method.name = name;
870 #else
871 m_strings.push_back(dup_string(name));
872 detail::method_rep& method = m_methods[m_strings.back()];
873 method.name = m_strings.back();
874 #endif
876 method.add_overload(o);
877 method.crep = this;
880 void luabind::detail::class_rep::add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
882 callback c;
883 c.func = g;
884 c.pointer_offset = 0;
885 #ifndef LUABIND_DONT_COPY_STRINGS
886 m_strings.push_back(dup_string(name));
887 m_getters[m_strings.back()] = c;
888 #else
889 m_getters[name] = c;
890 #endif
893 void luabind::detail::class_rep::add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
895 callback c;
896 c.func = s;
897 c.pointer_offset = 0;
898 #ifndef LUABIND_DONT_COPY_STRINGS
899 m_strings.push_back(dup_string(name));
900 m_setters[m_strings.back()] = c;
901 #else
902 m_setters[name] = c;
903 #endif
906 #ifndef LUABIND_NO_ERROR_CHECKING
907 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)
908 #else
909 void luabind::detail::class_rep::add_operator(lua_State*, int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
910 #endif
912 operator_callback o;
913 o.set_fun(func);
914 o.set_match_fun(matcher);
915 o.set_arity(arity);
917 #ifndef LUABIND_NO_ERROR_CHECKING
919 o.set_sig_fun(sig);
921 #endif
922 m_operators[op_id].push_back(o);
925 void luabind::detail::class_rep::add_static_constant(const char* name, int val)
927 #ifndef LUABIND_DONT_COPY_STRINGS
928 m_strings.push_back(dup_string(name));
929 m_static_constants[m_strings.back()] = val;
930 #else
931 m_static_constants[name] = val;
932 #endif
935 int luabind::detail::class_rep::super_callback(lua_State* L)
937 int args = lua_gettop(L);
939 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, lua_upvalueindex(2)));
940 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
941 class_rep* base = crep->bases()[0].base;
943 if (base->get_class_type() == class_rep::lua_class)
945 if (base->bases().empty())
947 obj->set_flags(obj->flags() & ~object_rep::call_super);
949 lua_pushstring(L, "super");
950 lua_pushnil(L);
951 lua_settable(L, LUA_GLOBALSINDEX);
953 else
955 lua_pushstring(L, "super");
956 lua_pushlightuserdata(L, base);
957 lua_pushvalue(L, lua_upvalueindex(2));
958 lua_pushcclosure(L, super_callback, 2);
959 lua_settable(L, LUA_GLOBALSINDEX);
962 detail::getref(L, base->table_ref());
963 lua_pushstring(L, "__init");
964 lua_gettable(L, -2);
965 lua_insert(L, 1);
966 lua_pop(L, 1);
968 lua_pushvalue(L, lua_upvalueindex(2));
969 lua_insert(L, 2);
971 lua_call(L, args + 1, 0);
973 // TODO: instead of clearing the global variable "super"
974 // store it temporarily in the registry. maybe we should
975 // have some kind of warning if the super global is used?
976 lua_pushstring(L, "super");
977 lua_pushnil(L);
978 lua_settable(L, LUA_GLOBALSINDEX);
980 else
982 obj->set_flags(obj->flags() & ~object_rep::call_super);
984 // we need to push some garbage at index 1 to make the construction work
985 lua_pushboolean(L, 1);
986 lua_insert(L, 1);
988 construct_rep* rep = &base->m_constructor;
990 bool ambiguous = false;
991 int match_index = -1;
992 int min_match = std::numeric_limits<int>::max();
993 bool found;
995 #ifdef LUABIND_NO_ERROR_CHECKING
997 if (rep->overloads.size() == 1)
999 match_index = 0;
1001 else
1004 #endif
1006 int num_params = lua_gettop(L) - 1;
1007 found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);
1009 #ifdef LUABIND_NO_ERROR_CHECKING
1013 #else
1015 if (!found)
1018 std::string msg = "no constructor of '";
1019 msg += base->m_name;
1020 msg += "' matched the arguments (";
1021 msg += stack_content_by_name(L, 2);
1022 msg += ")";
1023 lua_pushstring(L, msg.c_str());
1025 lua_error(L);
1027 else if (ambiguous)
1030 std::string msg = "call of overloaded constructor '";
1031 msg += base->m_name;
1032 msg += "(";
1033 msg += stack_content_by_name(L, 2);
1034 msg += ")' is ambiguous";
1035 lua_pushstring(L, msg.c_str());
1037 lua_error(L);
1040 // TODO: should this be a warning or something?
1042 // since the derived class is a lua class
1043 // it may have reimplemented virtual functions
1044 // therefore, we have to instantiate the Basewrapper
1045 // if there is no basewrapper, throw a run-time error
1046 if (!rep->overloads[match_index].has_wrapped_construct())
1049 std::string msg = "Cannot derive from C++ class '";
1050 msg += base->name();
1051 msg += "'. It does not have a wrapped type";
1052 lua_pushstring(L, msg.c_str());
1054 lua_error(L);
1057 #endif
1059 #ifndef LUABIND_NO_EXCEPTIONS
1064 #endif
1065 void* storage_ptr = obj->ptr();
1067 if (!rep->overloads[match_index].has_wrapped_construct())
1069 // if the type doesn't have a wrapped type, use the ordinary constructor
1070 void* instance = rep->overloads[match_index].construct(L);
1072 if (crep->has_holder())
1074 crep->m_construct_holder(storage_ptr, instance);
1076 else
1078 obj->set_object(instance);
1081 else
1083 // get reference to lua object
1084 lua_pushvalue(L, lua_upvalueindex(2));
1085 int ref = detail::ref(L);
1087 void* instance = rep->overloads[match_index].construct_wrapped(L, ref);
1089 if (crep->has_holder())
1091 crep->m_construct_holder(storage_ptr, instance);
1093 else
1095 obj->set_object(instance);
1098 // TODO: is the wrapped type destructed correctly?
1099 // it should, since the destructor is either the wrapped type's
1100 // destructor or the base type's destructor, depending on wether
1101 // the type has a wrapped type or not.
1102 obj->set_destructor(base->destructor());
1103 return 0;
1105 #ifndef LUABIND_NO_EXCEPTIONS
1108 catch(const std::exception& e)
1110 lua_pushstring(L, e.what());
1112 catch(const char* s)
1114 lua_pushstring(L, s);
1116 catch(...)
1118 std::string msg = base->m_name;
1119 msg += "() threw an exception";
1120 lua_pushstring(L, msg.c_str());
1122 // can only be reached if an exception was thrown
1123 lua_error(L);
1124 #endif
1127 return 0;
1133 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L)
1135 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1136 detail::getref(L, crep->m_table_ref);
1137 lua_replace(L, 1);
1138 lua_rawset(L, -3);
1140 crep->m_operator_cache = 0; // invalidate cache
1142 return 0;
1145 int luabind::detail::class_rep::construct_lua_class_callback(lua_State* L)
1147 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1149 int args = lua_gettop(L);
1151 // lua stack: crep <arguments>
1153 lua_newtable(L);
1154 int ref = detail::ref(L);
1156 bool has_bases = !crep->bases().empty();
1158 if (has_bases)
1160 lua_pushstring(L, "super");
1161 lua_pushvalue(L, 1); // crep
1164 // lua stack: crep <arguments> "super" crep
1165 // or
1166 // lua stack: crep <arguments>
1168 // if we have a baseclass we set the flag to say that the super has not yet been called
1169 // we will use this flag later to check that it actually was called from __init()
1170 int flags = object_rep::lua_class | object_rep::owner | (has_bases ? object_rep::call_super : 0);
1172 // void* obj_ptr = lua_newuserdata(L, sizeof(object_rep));
1173 void* obj_ptr;
1174 void* held_storage;
1176 boost::tie(obj_ptr, held_storage) = crep->allocate(L);
1177 (new(obj_ptr) object_rep(crep, flags, ref))->set_object(held_storage);
1179 detail::getref(L, crep->metatable_ref());
1180 lua_setmetatable(L, -2);
1182 // lua stack: crep <arguments> "super" crep obj_ptr
1183 // or
1184 // lua stack: crep <arguments> obj_ptr
1186 if (has_bases) lua_pushvalue(L, -1); // obj_ptr
1187 lua_replace(L, 1); // obj_ptr
1189 // lua stack: obj_ptr <arguments> "super" crep obj_ptr
1190 // or
1191 // lua stack: obj_ptr <arguments>
1193 if (has_bases)
1195 lua_pushcclosure(L, super_callback, 2);
1196 // lua stack: crep <arguments> "super" function
1197 lua_settable(L, LUA_GLOBALSINDEX);
1200 // lua stack: crep <arguments>
1202 lua_pushvalue(L, 1);
1203 lua_insert(L, 1);
1205 detail::getref(L, crep->table_ref());
1206 lua_pushstring(L, "__init");
1207 lua_gettable(L, -2);
1209 #ifndef LUABIND_NO_ERROR_CHECKING
1211 // TODO: should this be a run-time error?
1212 // maybe the default behavior should be to just call
1213 // the base calss' constructor. We should register
1214 // the super callback funktion as __init
1215 if (!lua_isfunction(L, -1))
1218 std::string msg = crep->name();
1219 msg += ":__init is not defined";
1220 lua_pushstring(L, msg.c_str());
1222 lua_error(L);
1225 #endif
1227 lua_insert(L, 2); // function first on stack
1228 lua_pop(L, 1);
1229 // TODO: lua_call may invoke longjump! make sure we don't have any memory leaks!
1230 // we don't have any stack objects here
1231 lua_call(L, args, 0);
1233 #ifndef LUABIND_NO_ERROR_CHECKING
1235 object_rep* obj = static_cast<object_rep*>(obj_ptr);
1236 if (obj->flags() & object_rep::call_super)
1238 lua_pushstring(L, "derived class must call super on base");
1239 lua_error(L);
1242 #endif
1244 return 1;
1247 // called from the metamethod for __index
1248 // obj is the object pointer
1249 int luabind::detail::class_rep::lua_class_gettable(lua_State* L)
1251 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1252 class_rep* crep = obj->crep();
1254 #ifndef LUABIND_NO_ERROR_CHECKING
1256 if (obj->flags() & object_rep::call_super)
1258 lua_pushstring(L, "derived class must call super on base");
1259 lua_error(L);
1262 #endif
1264 // we have to ignore the first argument since this may point to
1265 // a method that is not present in this class (but in a subclass)
1267 // BUG: This might catch members called "__ok\0foobar"
1268 const char* key = lua_tostring(L, 2);
1270 if (key && !std::strcmp(key, "__ok"))
1272 class_rep* crep = obj->crep();
1274 void* p = crep->extractor() ? crep->extractor()(obj->ptr())
1275 : obj->ptr();
1277 lua_pushboolean(L, p != 0);
1278 return 1;
1281 detail::getref(L, obj->lua_table_ref());
1282 lua_pushvalue(L, 2);
1283 lua_gettable(L, -2);
1285 if (!lua_isnil(L, -1))
1287 lua_remove(L, -2); // remove table
1288 return 1;
1291 lua_pop(L, 2);
1293 detail::getref(L, crep->table_ref());
1294 lua_pushvalue(L, 2);
1295 lua_gettable(L, -2);
1297 if (!lua_isnil(L, -1))
1299 lua_remove(L, -2); // more table
1300 return 1;
1303 lua_pop(L, 2);
1305 if (lua_isnil(L, 2))
1307 lua_pushnil(L);
1308 return 1;
1311 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1312 if (i != crep->m_methods.end())
1314 // the name is a method, return it
1315 lua_pushlightuserdata(L, &i->second);
1316 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1317 return 1;
1320 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_getters.find(key);
1321 if (j != crep->m_getters.end())
1323 // the name is a data member
1324 return j->second.func(L, j->second.pointer_offset);
1327 lua_pushnil(L);
1328 return 1;
1331 // called from the metamethod for __newindex
1332 // obj is the object pointer
1333 int luabind::detail::class_rep::lua_class_settable(lua_State* L)
1335 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1336 class_rep* crep = obj->crep();
1338 #ifndef LUABIND_NO_ERROR_CHECKING
1340 if (obj->flags() & object_rep::call_super)
1342 // this block makes sure the std::string is destructed
1343 // before lua_error is called
1345 std::string msg = "derived class '";
1346 msg += crep->name();
1347 msg += "'must call super on base";
1348 lua_pushstring(L, msg.c_str());
1350 lua_error(L);
1353 #endif
1355 // we have to ignore the first argument since this may point to
1356 // a method that is not present in this class (but in a subclass)
1357 // BUG: This will not work with keys with extra nulls in them
1358 const char* key = lua_tostring(L, 2);
1359 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_setters.find(key);
1361 if (j == crep->m_setters.end())
1363 std::map<const char*, class_rep::callback, ltstr>::iterator k = crep->m_getters.find(key);
1365 #ifndef LUABIND_NO_ERROR_CHECKING
1367 if (k != crep->m_getters.end())
1370 std::string msg = "cannot set property '";
1371 msg += crep->name();
1372 msg += ".";
1373 msg += key;
1374 msg += "', because it's read only";
1375 lua_pushstring(L, msg.c_str());
1377 lua_error(L);
1380 #endif
1382 detail::getref(L, obj->lua_table_ref());
1383 lua_replace(L, 1);
1384 lua_settable(L, 1);
1386 else
1388 // the name is a data member
1389 j->second.func(L, j->second.pointer_offset);
1392 return 0;
1395 int luabind::detail::class_rep::static_class_gettable(lua_State* L)
1397 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1399 // this has changed! c++ classes now also store their methods in the table
1400 // if (crep->get_class_type() == class_rep::lua_class)
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);
1409 // BUG: This will not work with keys with extra nulls in them
1410 const char* key = lua_tostring(L, 2);
1412 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1413 if (i != crep->m_methods.end())
1415 // the name is a method, return it
1416 lua_pushlightuserdata(L, &i->second);
1417 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1418 return 1;
1421 std::map<const char*, int, ltstr>::const_iterator j = crep->m_static_constants.find(key);
1423 if (j != crep->m_static_constants.end())
1425 lua_pushnumber(L, j->second);
1426 return 1;
1429 #ifndef LUABIND_NO_ERROR_CHECKING
1432 std::string msg = "no static '";
1433 msg += key;
1434 msg += "' in class '";
1435 msg += crep->name();
1436 msg += "'";
1437 lua_pushstring(L, msg.c_str());
1439 lua_error(L);
1441 #endif
1443 lua_pushnil(L);
1445 return 1;
1448 bool luabind::detail::is_class_rep(lua_State* L, int index)
1450 if (lua_getmetatable(L, index) == 0) return false;
1452 lua_pushstring(L, "__luabind_classrep");
1453 lua_gettable(L, -2);
1454 if (lua_toboolean(L, -1))
1456 lua_pop(L, 2);
1457 return true;
1460 lua_pop(L, 2);
1461 return false;
1464 void luabind::detail::finalize(lua_State* L, class_rep* crep)
1466 if (crep->get_class_type() != class_rep::lua_class) return;
1468 // lua_pushvalue(L, -1); // copy the object ref
1469 detail::getref(L, crep->table_ref());
1470 lua_pushstring(L, "__finalize");
1471 lua_gettable(L, -2);
1472 lua_remove(L, -2);
1474 if (lua_isnil(L, -1))
1476 lua_pop(L, 1);
1478 else
1480 lua_pushvalue(L, -2);
1481 lua_call(L, 1, 0);
1484 for (std::vector<class_rep::base_info>::const_iterator
1485 i = crep->bases().begin(); i != crep->bases().end(); ++i)
1487 if (i->base) finalize(L, i->base);
1491 void* luabind::detail::class_rep::convert_to(LUABIND_TYPE_INFO target_type, const object_rep* obj, void* target_memory) const
1493 // TODO: since this is a member function, we don't have to use the accesor functions for
1494 // the types and the extractor
1496 int steps = 0;
1497 int offset = 0;
1498 if (!(LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), target_type))
1499 && !(LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), target_type)))
1501 steps = implicit_cast(this, target_type, offset);
1504 // should never be called with a type that can't be cast
1505 assert((steps >= 0) && "internal error, please report");
1507 if (LUABIND_TYPE_INFO_EQUAL(target_type, holder_type()))
1509 // if the type we are trying to convert to is the holder_type
1510 // it means that his crep has a holder_type (since it would have
1511 // been invalid otherwise, and T cannot be invalid). It also means
1512 // that we need no conversion, since the holder_type is what the
1513 // object points to.
1514 return obj->ptr();
1517 if (LUABIND_TYPE_INFO_EQUAL(target_type, const_holder_type()))
1519 if (obj->flags() & object_rep::constant)
1521 // we are holding a constant
1522 return obj->ptr();
1524 else
1526 // we are holding a non-constant, we need to convert it
1527 // to a const_holder.
1528 m_const_converter(obj->ptr(), target_memory);
1529 return target_memory;
1533 void* raw_pointer;
1535 if (has_holder())
1537 // this means that we have a holder type where the
1538 // raw-pointer needs to be extracted
1539 raw_pointer = extractor()(obj->ptr());
1541 else
1543 raw_pointer = obj->ptr();
1546 return static_cast<char*>(raw_pointer) + offset;
1549 void luabind::detail::class_rep::cache_operators(lua_State* L)
1551 m_operator_cache = 0x1;
1553 for (int i = 0; i < number_of_operators; ++i)
1555 getref(L, table_ref());
1556 lua_pushstring(L, get_operator_name(i));
1557 lua_rawget(L, -2);
1559 if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1);
1561 lua_pop(L, 2);
1565 bool luabind::detail::class_rep::has_operator_in_lua(lua_State* L, int id)
1567 if ((m_operator_cache & 0x1) == 0)
1568 cache_operators(L);
1570 const int mask = 1 << (id + 1);
1572 return (m_operator_cache & mask) != 0;
1575 void luabind::detail::class_rep::add_method(lua_State* L, const char* name, detail::method_rep& m)
1577 detail::getref(L, table_ref());
1578 lua_pushstring(L, name);
1579 lua_gettable(L, -2);
1581 if (lua_isnil(L, -1) || !lua_iscfunction(L, -1))
1583 lua_pop(L, 1);
1584 lua_pushstring(L, name);
1585 lua_pushlightuserdata(L, const_cast<void*>((const void*)&m));
1586 lua_pushcclosure(L, function_dispatcher, 1);
1587 lua_settable(L, -3);
1588 lua_pop(L, 1);
1590 else
1592 lua_getupvalue(L, -1, 1);
1593 method_rep* inherited = static_cast<method_rep*>(lua_touserdata(L, -1));
1595 for (std::vector<overload_rep>::const_iterator i = inherited->overloads().begin();
1596 i != inherited->overloads().end(); ++i)
1598 m.add_overload(*i);
1601 detail::getref(L, table_ref());
1602 lua_pushstring(L, name);
1603 lua_pushlightuserdata(L, const_cast<void*>((const void*)&m));
1604 lua_pushcclosure(L, function_dispatcher, 1);
1605 lua_settable(L, -3);
1606 lua_pop(L, 4);
1610 const class_rep::property_map& luabind::detail::class_rep::properties() const
1612 return m_getters;