Initial revision
[luabind.git] / luabind / detail / class_rep.hpp
blob40e2ef442bfec22bf43950b61cece0e1760372c3
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.
24 #ifndef LUABIND_CLASS_REP_HPP_INCLUDED
25 #define LUABIND_CLASS_REP_HPP_INCLUDED
27 //#include <cstdlib>
29 #include <boost/limits.hpp>
30 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
32 #include <luabind/config.hpp>
33 #include <luabind/detail/object_rep.hpp>
34 #include <luabind/detail/construct_rep.hpp>
35 #include <luabind/detail/method_rep.hpp>
36 #include <luabind/detail/garbage_collector.hpp>
37 #include <luabind/detail/operator_id.hpp>
38 #include <luabind/detail/signature_match.hpp>
39 #include <luabind/detail/class_registry.hpp>
40 #include <luabind/detail/find_best_match.hpp>
41 #include <luabind/detail/get_overload_signature.hpp>
42 #include <luabind/detail/error.hpp>
44 namespace luabind
47 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(LUABIND_MAX_BASES, class A, detail::null_type)>
48 struct bases {};
49 typedef bases<detail::null_type> no_bases;
53 namespace luabind { namespace detail
55 std::string stack_content_by_name(lua_State* L, int start_index);
56 int construct_lua_class_callback(lua_State* L);
58 // this is class-specific information, poor man's vtable
59 // this is allocated statically (removed by the compiler)
60 // a pointer to this structure is stored in the lua tables'
61 // metatable with the name __classrep
62 // it is used when matching parameters to function calls
63 // to determine possible implicit casts
64 // it is also used when finding the best match for overloaded
65 // methods
66 class class_rep
68 friend int super_callback(lua_State*);
69 friend int lua_class_gettable(lua_State*);
70 friend int lua_class_settable(lua_State*);
71 friend int static_class_gettable(lua_State*);
72 public:
74 enum class_type
76 cpp_class = 0,
77 lua_class = 1
82 // destructor is a lua callback function that is hooked as garbage collector event on every instance
83 // of this class (including those that is not owned by lua). It gets an object_rep as argument
84 // on the lua stack. It should delete the object pointed to by object_rep::ptr if object_pre::flags
85 // is object_rep::owner (which means that lua owns the object)
87 class_rep(LUABIND_TYPE_INFO t, const char* name, lua_State* L, void(*destructor)(void*), LUABIND_TYPE_INFO held_t, void*(*extractor)(void*))
88 : m_type(t)
89 , m_held_type(held_t)
90 , m_extract_underlying_fun(extractor)
91 , m_name(name)
92 , m_class_type(cpp_class)
93 , m_destructor(destructor)
95 class_registry* r = class_registry::get_registry(L);
96 assert(r->m_cpp_class_metatable != LUA_NOREF); // you must call luabind::open()
98 detail::getref(L, r->m_cpp_class_metatable);
99 lua_setmetatable(L, -2);
101 m_self_ref = detail::ref(L);
103 // make our class_rep public by putting it in the globals table
104 #ifdef LUABIND_DONT_COPY_STRINGS
105 lua_pushstring(L, m_name);
106 #else
107 lua_pushstring(L, m_name.c_str());
108 #endif
109 detail::getref(L, m_self_ref);
110 lua_settable(L, LUA_GLOBALSINDEX);
112 m_instance_metatable = r->m_cpp_instance_metatable;
115 // used when creating a lua class
116 class_rep(lua_State* L, const char* name)
117 : m_type(LUABIND_TYPEID(int))
118 , m_held_type(0)
119 , m_extract_underlying_fun(0)
120 , m_name(name)
121 , m_class_type(lua_class)
123 lua_newtable(L);
124 m_table_ref = detail::ref(L);
126 class_registry* r = class_registry::get_registry(L);
127 assert(r->m_cpp_class_metatable != LUA_NOREF); // you must call luabind::open()
129 detail::getref(L, r->m_lua_class_metatable);
130 lua_setmetatable(L, -2);
131 m_self_ref = detail::ref(L);
133 // make our class_rep public by putting it in the globals table
134 #ifdef LUABIND_DONT_COPY_STRINGS
135 lua_pushstring(L, m_name);
136 #else
137 lua_pushstring(L, m_name.c_str());
138 #endif
139 detail::getref(L, m_self_ref);
140 lua_settable(L, LUA_GLOBALSINDEX);
142 m_instance_metatable = r->m_lua_instance_metatable;
145 ~class_rep()
147 #ifndef LUABIND_DONT_COPY_STRINGS
148 for (std::vector<char*>::iterator i = m_strings.begin(); i != m_strings.end(); ++i)
150 delete[] *i;
152 #endif
156 // called from the metamethod for __index
157 // the object pointer is passed on the lua stack
158 int gettable(lua_State* L)
160 // we have to ignore the first argument since this may point to
161 // a method that is not present in this class (but in a subclass)
162 const char* key = lua_tostring(L, 2);
163 std::map<const char*, method_rep, ltstr>::iterator i = m_methods.find(key);
164 if (i != m_methods.end())
166 // the name is a method, return it
167 lua_pushlightuserdata(L, &i->second);
168 lua_pushcclosure(L, function_dispatcher, 1);
169 return 1;
172 std::map<const char*, callback, ltstr>::iterator j = m_getters.find(key);
173 if (j != m_getters.end())
175 // the name is a data member
176 return j->second.func(L, j->second.pointer_offset);
179 return 0;
182 // called from the metamethod for __newindex
183 // the object pointer is passed on the lua stack
184 bool settable(lua_State* L)
186 // we have to ignore the first argument since this may point to
187 // a method that is not present in this class (but in a subclass)
188 const char* key = lua_tostring(L, 2);
189 std::map<const char*, callback, ltstr>::iterator j = m_setters.find(key);
190 if (j != m_setters.end())
192 // the name is a data member
193 j->second.func(L, j->second.pointer_offset);
194 return true;
197 return false; // false means that we don't have a member with the given name
200 // this is called as __index metamethod on every instance of this class
201 static int gettable_dispatcher(lua_State* L)
203 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
204 return obj->crep()->gettable(L);
207 // this is called as __newindex metamethod on every instance of this class
208 static int settable_dispatcher(lua_State* L)
210 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
212 bool success = obj->crep()->settable(L);
214 #ifndef LUABIND_NO_ERROR_CHECKING
216 if (!success)
218 // this block is needed to make sure the std::string is destructed before
219 // lua_error() is called
220 #ifdef BOOST_MSVC
222 // msvc has a bug which deletes the string twice, that's
223 // why we have to create it on the heap
224 std::string* msg = new std::string("cannot set attribute '");
225 *msg += obj->crep()->m_name;
226 *msg += ".";
227 *msg += lua_tostring(L, -2);
228 *msg += "'";
229 lua_pushstring(L, msg->c_str());
230 delete msg;
232 #else
234 std::string msg = "cannot set attribute '";
235 msg += obj->crep()->m_name;
236 msg += ".";
237 msg += lua_tostring(L, -2);
238 msg += "'";
239 lua_pushstring(L, msg.c_str());
241 #endif
242 lua_error(L);
245 #endif
247 return 0;
250 static int operator_dispatcher(lua_State* L)
252 int id = static_cast<int>(lua_tonumber(L, lua_upvalueindex(1)));
254 int operand_id = 0;
256 object_rep* operand[2];
257 for (int i = 0; i < 2; ++i)
258 operand[i] = detail::is_class_object(L, i + 1);
260 if (operand[0] && operand[1])
261 if (LUABIND_TYPE_INFO_EQUAL(operand[0]->crep()->type(), operand[1]->crep()->type())) operand[1] = 0;
263 std::vector<operator_callback>* overloads[2];
264 for (int i = 0; i < 2; ++i)
265 if (operand[i]) overloads[i] = &operand[i]->crep()->m_operators[id]; else overloads[i] = 0;
267 int num_overloads[2];
268 for (int i = 0; i < 2; ++i)
269 if (overloads[i]) num_overloads[i] = overloads[i]->size(); else num_overloads[i] = 0;
271 bool ambiguous = false;
272 int match_index = -1;
273 int min_match = std::numeric_limits<int>::max();
275 // std::cout << "operator_dispatcher\n";
276 // std::cout << "num overloads: " << num_overloads[0] + num_overloads[1] << "\n";
277 // std::cout << "operator: " << id << "\n";
279 #ifdef LUABIND_NO_ERROR_CHECKING
281 if (num_overloads[0] == 1 && num_overloads[1] == 0)
283 operand_id = 0;
284 match_index = 0;
286 else if (num_overloads[0] == 0 && num_overloads[1] == 1)
288 operand_id = 1;
289 match_index = 0;
291 else
294 #endif
296 int num_params = lua_gettop(L);
297 if (overloads[0])
299 if (find_best_match(L, overloads[0]->begin(), overloads[0]->end(), ambiguous, min_match, match_index, num_params))
300 operand_id = 0;
303 // have look at the right operand.
304 // if the right operand is a class and
305 // not the same class as this, we have to
306 // try to match it's operators too
308 if (overloads[1])
310 if(find_best_match(L, overloads[1]->begin(), overloads[1]->end(), ambiguous, min_match, match_index, num_params))
311 operand_id = 1;
314 #ifdef LUABIND_NO_ERROR_CHECKING
318 #else
320 if (match_index == -1)
322 // this block is needed to make sure the std::string is destructed before
323 // lua_error() is called
325 std::string msg = "no operator ";
326 msg += get_operator_symbol(id);
327 msg += " matched the arguments (";
328 msg += stack_content_by_name(L, 1);
329 msg += ")\ncandidates are:\n";
331 if (overloads[0])
332 msg += get_overload_signatures(L, overloads[0]->begin(), overloads[0]->end(), get_operator_symbol(id));
334 if (overloads[1])
335 msg += get_overload_signatures(L, overloads[1]->begin(), overloads[1]->end(), get_operator_symbol(id));
337 lua_pushstring(L, msg.c_str());
339 lua_error(L);
341 else if (ambiguous)
343 // this block is needed to make sure the std::string is destructed before
344 // lua_error() is called
346 std::string msg = "call of overloaded operator ";
347 msg += get_operator_symbol(id);
348 msg += " (";
349 msg += stack_content_by_name(L, 1);
350 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
352 std::vector<operator_callback> candidates;
353 if (overloads[0])
354 find_exact_match(L, overloads[0]->begin(), overloads[0]->end(), min_match, num_params, candidates);
356 if (overloads[1])
357 find_exact_match(L, overloads[1]->begin(), overloads[1]->end(), min_match, num_params, candidates);
359 msg += get_overload_signatures(L, candidates.begin(), candidates.end(), get_operator_symbol(id));
362 lua_pushstring(L, msg.c_str());
364 lua_error(L);
367 #endif
369 return (*overloads[operand_id])[match_index].call(L);
373 // this is called as metamethod __call on the class_rep.
374 static int constructor_dispatcher(lua_State* L)
376 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
377 construct_rep* rep = &crep->m_constructor;
379 bool ambiguous = false;
380 int match_index = -1;
381 int min_match = std::numeric_limits<int>::max();
382 bool found;
384 #ifdef LUABIND_NO_ERROR_CHECKING
386 if (rep->overloads.size() == 1)
388 match_index = 0;
390 else
393 #endif
395 int num_params = lua_gettop(L) - 1;
396 found = find_best_match(L, rep->overloads.begin(), rep->overloads.end(), ambiguous, min_match, match_index, num_params);
398 #ifdef LUABIND_NO_ERROR_CHECKING
402 #else
404 if (!found)
406 // this block is needed to make sure the std::string is destructed before
407 // lua_error() is called
409 std::string msg = "no constructor of '";
410 msg += crep->name();
411 msg += "' matched the arguments (";
412 msg += stack_content_by_name(L, 2);
413 msg += ")\n candidates are:\n";
415 msg += get_overload_signatures(L, rep->overloads.begin(), rep->overloads.end(), crep->name());
417 lua_pushstring(L, msg.c_str());
419 lua_error(L);
421 else if (ambiguous)
423 // this block is needed to make sure the std::string is destructed before
424 // lua_error() is called
426 std::string msg = "call of overloaded constructor '";
427 msg += crep->m_name;
428 msg += "(";
429 msg += stack_content_by_name(L, 2);
430 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
432 std::vector<construct_rep::overload_t> candidates;
433 find_exact_match(L, rep->overloads.begin(), rep->overloads.end(), min_match, num_params, candidates);
434 msg += get_overload_signatures(L, candidates.begin(), candidates.end(), crep->name());
436 lua_pushstring(L, msg.c_str());
438 lua_error(L);
441 #endif
443 #ifndef LUABIND_NO_EXCEPTIONS
448 #endif
450 void* object_ptr = rep->overloads[match_index].construct(L);
452 void* obj_rep = lua_newuserdata(L, sizeof(object_rep));
453 new(obj_rep) object_rep(object_ptr, crep, object_rep::owner, crep->destructor());
455 detail::getref(L, crep->m_instance_metatable);
456 lua_setmetatable(L, -2);
457 return 1;
459 #ifndef LUABIND_NO_EXCEPTIONS
463 catch(const std::exception& e)
465 lua_pushstring(L, e.what());
467 catch(const char* s)
469 lua_pushstring(L, s);
471 catch(...)
474 std::string msg = crep->name();
475 msg += "() threw an exception";
476 lua_pushstring(L, msg.c_str());
480 // we can only reach this line if an exception was thrown
481 lua_error(L);
482 return 0; // will never be reached
484 #endif
488 static int implicit_cast(const class_rep* from, const class_rep* to, int& pointer_offset)
490 int offset = 0;
491 if (LUABIND_TYPE_INFO_EQUAL(from->type(), to->type())) return 0;
493 for (std::vector<class_rep::base_info>::const_iterator i = from->bases().begin(); i != from->bases().end(); ++i)
495 int steps = implicit_cast(i->base, to, offset);
496 pointer_offset = offset + i->pointer_offset;
497 if (steps >= 0) return steps + 2;
499 return -1;
502 // the functions dispatcher assumes the following:
503 // there is one upvalue that points to the method_rep that this dispatcher is to call
504 // the first parameter on the lua stack is an object_rep that points to the object the
505 // call is being made on
506 static int function_dispatcher(lua_State* L)
508 method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
509 object_rep* obj = reinterpret_cast<object_rep*>(lua_touserdata(L, 1));
511 #ifndef LUABIND_NO_ERROR_CHECKING
513 if (is_class_object(L, 1) == 0)
516 std::string msg = "No self reference given as first parameter to member function '";
517 msg += rep->crep->name();
518 msg += ":";
519 msg += rep->name;
520 msg += "'. Have you used '.' instead of ':'?";
522 lua_pushstring(L, msg.c_str());
524 lua_error(L);
527 int p;
528 if (implicit_cast(obj->crep(), rep->crep, p) < 0)
531 std::string msg = "invalid self reference given to '";
532 msg += rep->crep->name();
533 msg += ":";
534 msg += rep->name;
535 msg += "'";
536 lua_pushstring(L, msg.c_str());
538 lua_error(L);
541 #endif
543 bool ambiguous = false;
544 int match_index = -1;
545 int min_match = std::numeric_limits<int>::max();
546 bool found;
548 #ifdef LUABIND_NO_ERROR_CHECKING
549 if (rep->overloads().size() == 1)
551 match_index = 0;
553 else
555 #endif
557 int num_params = lua_gettop(L) - 1;
558 found = find_best_match(L, rep->overloads().begin(), rep->overloads().end(), ambiguous, min_match, match_index, num_params);
560 #ifdef LUABIND_NO_ERROR_CHECKING
564 #else
566 if (!found)
569 std::string msg = "no overload of '";
570 msg += rep->crep->name();
571 msg += ":";
572 msg += rep->name;
573 msg += "' matched the arguments (";
574 msg += stack_content_by_name(L, 2);
575 msg += ")\ncandidates are:\n";
577 std::string function_name;
578 function_name += rep->crep->name();
579 function_name += ":";
580 function_name += rep->name;
582 msg += get_overload_signatures(L, rep->overloads().begin(), rep->overloads().end(), function_name);
584 lua_pushstring(L, msg.c_str());
586 lua_error(L);
588 else if (ambiguous)
591 std::string msg = "call of overloaded '";
592 msg += rep->crep->name();
593 msg += ":";
594 msg += rep->name;
595 msg += "(";
596 msg += stack_content_by_name(L, 2);
597 msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
599 std::vector<overload_rep> candidates;
600 find_exact_match(L, rep->overloads().begin(), rep->overloads().end(), min_match, num_params, candidates);
602 std::string function_name;
603 function_name += rep->crep->name();
604 function_name += ":";
605 function_name += rep->name;
607 msg += get_overload_signatures(L, candidates.begin(), candidates.end(), function_name);
609 lua_pushstring(L, msg.c_str());
611 lua_error(L);
614 #endif
616 #ifndef LUABIND_NO_EXCEPTIONS
621 #endif
623 const overload_rep& o = rep->overloads()[match_index];
624 return o.call(L, *obj);
626 #ifndef LUABIND_NO_EXCEPTIONS
629 catch(const std::exception& e)
631 lua_pushstring(L, e.what());
633 catch (const char* s)
635 lua_pushstring(L, s);
637 catch(...)
639 std::string msg = rep->crep->name();
640 msg += ":";
641 msg += rep->name;
642 msg += "() threw an exception";
643 lua_pushstring(L, msg.c_str());
645 // we can only reach this line if an exception was thrown
646 lua_error(L);
647 return 0; // will never be reached
649 #endif
658 struct base_info
660 int pointer_offset; // the offset added to the pointer to obtain a basepointer (due to multiple-inheritance)
661 class_rep* base;
664 inline void add_base(const base_info& base)
666 int pointer_offset = base.pointer_offset;
668 // the baseclass' class_rep structure
669 class_rep* bcrep = base.base;
671 // import all functions from the base
672 for (std::map<const char*, method_rep, ltstr>::const_iterator i = bcrep->m_methods.begin(); i != bcrep->m_methods.end(); ++i)
674 #ifndef LUABIND_DONT_COPY_STRINGS
675 m_strings.push_back(dup_string(i->first));
676 method_rep& m = m_methods[m_strings.back()];
677 #else
678 method_rep& m = m_methods[i->first];
679 #endif
680 m.name = i->first;
681 m.crep = this;
683 for (std::vector<overload_rep>::const_iterator j = i->second.overloads().begin(); j != i->second.overloads().end(); ++j)
685 overload_rep o = *j;
686 o.add_offset(pointer_offset);
687 m.add_overload(o);
691 // import all getters from the base
692 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_getters.begin(); i != bcrep->m_getters.end(); ++i)
694 #ifndef LUABIND_DONT_COPY_STRINGS
695 m_strings.push_back(dup_string(i->first));
696 callback& m = m_getters[m_strings.back()];
697 #else
698 callback& m = m_getters[i->first];
699 #endif
700 m.pointer_offset = i->second.pointer_offset + pointer_offset;
701 m.func = i->second.func;
704 // import all setters from the base
705 for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_setters.begin(); i != bcrep->m_setters.end(); ++i)
707 #ifndef LUABIND_DONT_COPY_STRINGS
708 // TODO: optimize this by not copying the string if it already exists in m_setters.
709 // This goes for m_getters, m_static_constants and m_functions too. Both here
710 // in add_base() and in the add_function(), add_getter() ... functions.
711 m_strings.push_back(dup_string(i->first));
712 callback& m = m_setters[m_strings.back()];
713 #else
714 callback& m = m_setters[i->first];
715 #endif
716 m.pointer_offset = i->second.pointer_offset + pointer_offset;
717 m.func = i->second.func;
720 // import all static constants
721 for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin(); i != bcrep->m_static_constants.end(); ++i)
723 #ifndef LUABIND_DONT_COPY_STRINGS
724 m_strings.push_back(dup_string(i->first));
725 int& v = m_static_constants[m_strings.back()];
726 #else
727 int& v = m_static_constants[i->first];
728 #endif
729 v = i->second;
732 // import all operators
733 std::copy(bcrep->m_operators, bcrep->m_operators + number_of_operators, m_operators);
735 // also, save the baseclass info to be used for typecasts
736 m_bases.push_back(base);
739 inline const std::vector<base_info>& bases() const throw() { return m_bases; }
740 inline LUABIND_TYPE_INFO type() const throw() { return m_type; }
741 inline void set_type(LUABIND_TYPE_INFO t) { m_type = t; }
743 inline void add_function(const char* name, const overload_rep& o)
746 #ifdef LUABIND_DONT_COPY_STRINGS
747 detail::method_rep& method = m_methods[name];
748 method.name = name;
749 #else
750 m_strings.push_back(dup_string(name));
751 detail::method_rep& method = m_methods[m_strings.back()];
752 method.name = m_strings.back();
753 #endif
755 method.add_overload(o);
756 method.crep = this;
759 inline void add_constructor(const detail::construct_rep::overload_t& o)
761 m_constructor.overloads.push_back(o);
764 inline void add_wrapped_constructor(const detail::construct_rep::overload_t& o)
766 m_wrapped_constructor.overloads.push_back(o);
769 inline const char* name() const throw()
771 #ifdef LUABIND_DONT_COPY_STRINGS
772 return m_name;
773 #else
774 return m_name.c_str();
775 #endif
778 inline void add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
780 callback c;
781 c.func = g;
782 c.pointer_offset = 0;
783 #ifndef LUABIND_DONT_COPY_STRINGS
784 m_strings.push_back(dup_string(name));
785 m_getters[m_strings.back()] = c;
786 #else
787 m_getters[name] = c;
788 #endif
791 inline void add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
793 callback c;
794 c.func = s;
795 c.pointer_offset = 0;
796 #ifndef LUABIND_DONT_COPY_STRINGS
797 m_strings.push_back(dup_string(name));
798 m_setters[m_strings.back()] = c;
799 #else
800 m_setters[name] = c;
801 #endif
804 #ifndef LUABIND_NO_ERROR_CHECKING
805 inline void add_operator(lua_State*, int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), void(*sig)(lua_State*, std::string&), int arity)
806 #else
807 inline void add_operator(lua_State*, int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
808 #endif
810 operator_callback o;
811 o.set_fun(func);
812 o.set_match_fun(matcher);
813 o.set_arity(arity);
815 #ifndef LUABIND_NO_ERROR_CHECKING
817 o.set_sig_fun(sig);
819 #endif
820 m_operators[op_id].push_back(o);
823 // the lua reference to this class_rep
824 inline int self_ref() const throw() { return m_self_ref; }
826 // the lua reference to the metatable for this class' instances
827 inline int metatable_ref() const throw() { return m_instance_metatable; }
829 inline int table_ref() const { return m_table_ref; }
831 inline void(*destructor() const)(void*) { return m_destructor; }
833 inline class_type get_class_type() const { return m_class_type; }
835 void add_static_constant(const char* name, int val)
837 #ifndef LUABIND_DONT_COPY_STRINGS
838 m_strings.push_back(dup_string(name));
839 m_static_constants[m_strings.back()] = val;
840 #else
841 m_static_constants[name] = val;
842 #endif
845 static inline int super_callback(lua_State* L)
847 int args = lua_gettop(L);
849 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, lua_upvalueindex(2)));
850 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
851 class_rep* base = crep->bases()[0].base;
853 // std::cout << "__super of " << base->name() << "\n";
855 if (base->get_class_type() == class_rep::lua_class)
857 if (base->bases().empty())
859 obj->set_flags(obj->flags() & ~object_rep::call_super);
861 lua_pushstring(L, "super");
862 lua_pushnil(L);
863 lua_settable(L, LUA_GLOBALSINDEX);
865 else
867 lua_pushstring(L, "super");
868 lua_pushlightuserdata(L, base);
869 lua_pushvalue(L, lua_upvalueindex(2));
870 lua_pushcclosure(L, super_callback, 2);
871 lua_settable(L, LUA_GLOBALSINDEX);
874 // std::cout << " lua_class\n";
875 detail::getref(L, base->table_ref());
876 lua_pushstring(L, "__init");
877 lua_gettable(L, -2);
878 lua_insert(L, 1);
879 lua_pop(L, 1);
881 lua_pushvalue(L, lua_upvalueindex(2));
882 lua_insert(L, 2);
884 lua_call(L, args + 1, 0);
886 // TODO: instead of clearing the global variable "super"
887 // store it temporarily in the registry. maybe we should
888 // have some kind of warning if the super global is used?
889 lua_pushstring(L, "super");
890 lua_pushnil(L);
891 lua_settable(L, LUA_GLOBALSINDEX);
893 else
895 obj->set_flags(obj->flags() & ~object_rep::call_super);
896 // std::cout << " cpp_class\n";
898 // we need to push some garbage at index 1 to make the construction work
899 lua_pushboolean(L, 1);
900 lua_insert(L, 1);
902 construct_rep* rep = &base->m_constructor;
904 bool ambiguous = false;
905 int match_index = -1;
906 int min_match = std::numeric_limits<int>::max();
907 bool found;
909 #ifdef LUABIND_NO_ERROR_CHECKING
911 if (rep->overloads.size() == 1)
913 match_index = 0;
915 else
918 #endif
920 int num_params = lua_gettop(L) - 1;
921 found = find_best_match(L, rep->overloads.begin(), rep->overloads.end(), ambiguous, min_match, match_index, num_params);
923 #ifdef LUABIND_NO_ERROR_CHECKING
927 #else
929 if (!found)
932 std::string msg = "no constructor of '";
933 msg += base->m_name;
934 msg += "' matched the arguments (";
935 msg += stack_content_by_name(L, 2);
936 msg += ")";
937 lua_pushstring(L, msg.c_str());
939 lua_error(L);
941 else if (ambiguous)
944 std::string msg = "call of overloaded constructor '";
945 msg += base->m_name;
946 msg += "(";
947 msg += stack_content_by_name(L, 2);
948 msg += ")' is ambiguous";
949 lua_pushstring(L, msg.c_str());
951 lua_error(L);
954 // TODO: should this be a warning or something?
956 // since the derived class is a lua class
957 // it may have reimplemented virtual functions
958 // therefore, we have to instantiate the Basewrapper
959 // if there is no basewrapper, throw a run-time error
960 if (!rep->overloads[match_index].has_wrapped_construct())
963 std::string msg = "Cannot derive from C++ class '";
964 msg += base->name();
965 msg += "'. It does not have a wrapped type";
966 lua_pushstring(L, msg.c_str());
968 lua_error(L);
971 #endif
973 #ifndef LUABIND_NO_EXCEPTIONS
978 #endif
980 if (!rep->overloads[match_index].has_wrapped_construct())
982 // if the type doesn't have a wrapped type, use the ordinary constructor
983 obj->set_object(rep->overloads[match_index].construct(L));
985 else
987 // get reference to lua object
988 lua_pushvalue(L, lua_upvalueindex(2));
989 int ref = detail::ref(L);
990 obj->set_object(rep->overloads[match_index].construct_wrapped(L, ref));
992 // TODO: is the wrapped type destructed correctly?
993 // it should, since the destructor is either the wrapped type's
994 // destructor or the base type's destructor, depending on wether
995 // the type has a wrapped type or not.
996 obj->set_destructor(base->destructor());
997 return 0;
999 #ifndef LUABIND_NO_EXCEPTIONS
1002 catch(const std::exception& e)
1004 lua_pushstring(L, e.what());
1006 catch(const char* s)
1008 lua_pushstring(L, s);
1010 catch(...)
1012 std::string msg = base->m_name;
1013 msg += "() threw an exception";
1014 lua_pushstring(L, msg.c_str());
1016 // can only be reached if an exception was thrown
1017 lua_error(L);
1018 #endif
1021 return 0;
1025 static int lua_settable_dispatcher(lua_State* L)
1027 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1028 detail::getref(L, crep->m_table_ref);
1029 lua_replace(L, 1);
1030 lua_rawset(L, -3);
1031 return 0;
1034 static int construct_lua_class_callback(lua_State* L)
1036 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1038 int args = lua_gettop(L);
1040 // lua stack: crep <arguments>
1042 lua_newtable(L);
1043 int ref = detail::ref(L);
1045 bool has_bases = !crep->bases().empty();
1047 if (has_bases)
1049 lua_pushstring(L, "super");
1050 lua_pushvalue(L, 1); // crep
1053 // lua stack: crep <arguments> "super" crep
1054 // or
1055 // lua stack: crep <arguments>
1058 // if we have a baseclass we set the flag to say that the super has not yet been called
1059 // we will use this flag later to check that it actually was called from __init()
1060 int flags = object_rep::lua_class | object_rep::owner | (has_bases ? object_rep::call_super : 0);
1062 void* obj_ptr = lua_newuserdata(L, sizeof(object_rep));
1063 new(obj_ptr) object_rep(crep, flags, ref);
1065 detail::getref(L, crep->metatable_ref());
1066 lua_setmetatable(L, -2);
1068 // lua stack: crep <arguments> "super" crep obj_ptr
1069 // or
1070 // lua stack: crep <arguments> obj_ptr
1072 if (has_bases) lua_pushvalue(L, -1); // obj_ptr
1073 lua_replace(L, 1); // obj_ptr
1075 // lua stack: obj_ptr <arguments> "super" crep obj_ptr
1076 // or
1077 // lua stack: obj_ptr <arguments>
1079 if (has_bases)
1081 lua_pushcclosure(L, super_callback, 2);
1082 // lua stack: crep <arguments> "super" function
1083 lua_settable(L, LUA_GLOBALSINDEX);
1086 // lua stack: crep <arguments>
1088 lua_pushvalue(L, 1);
1089 lua_insert(L, 1);
1091 detail::getref(L, crep->table_ref());
1092 lua_pushstring(L, "__init");
1093 lua_gettable(L, -2);
1095 #ifndef LUABIND_NO_ERROR_CHECKING
1097 // TODO: should this be a run-time error?
1098 // maybe the default behavior should be to just call
1099 // the base calss' constructor. We should register
1100 // the super callback funktion as __init
1101 if (!lua_isfunction(L, -1))
1104 std::string msg = crep->name();
1105 msg += ":__init is not defined";
1106 lua_pushstring(L, msg.c_str());
1108 lua_error(L);
1111 #endif
1113 lua_insert(L, 2); // function first on stack
1114 lua_pop(L, 1);
1115 // TODO: lua_call may invoke longjump! make sure we don't have any memory leaks!
1116 // we don't have any stack objects here
1117 lua_call(L, args, 0);
1119 #ifndef LUABIND_NO_ERROR_CHECKING
1121 object_rep* obj = static_cast<object_rep*>(obj_ptr);
1122 if (obj->flags() & object_rep::call_super)
1124 lua_pushstring(L, "derived class must call super on base");
1125 lua_error(L);
1128 #endif
1130 return 1;
1133 // called from the metamethod for __index
1134 // obj is the object pointer
1135 static int lua_class_gettable(lua_State* L)
1137 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1138 class_rep* crep = obj->crep();
1140 #ifndef LUABIND_NO_ERROR_CHECKING
1142 if (obj->flags() & object_rep::call_super)
1144 lua_pushstring(L, "derived class must call super on base");
1145 lua_error(L);
1148 #endif
1150 detail::getref(L, obj->lua_table_ref());
1151 lua_pushvalue(L, 2);
1152 lua_gettable(L, -2);
1154 if (!lua_isnil(L, -1)) return 1;
1156 lua_pop(L, 2);
1158 detail::getref(L, crep->table_ref());
1159 lua_pushvalue(L, 2);
1160 lua_gettable(L, -2);
1162 if (!lua_isnil(L, -1)) return 1;
1164 lua_pop(L, 2);
1166 // we have to ignore the first argument since this may point to
1167 // a method that is not present in this class (but in a subclass)
1168 const char* key = lua_tostring(L, 2);
1170 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1171 if (i != crep->m_methods.end())
1173 // the name is a method, return it
1174 lua_pushlightuserdata(L, &i->second);
1175 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1176 return 1;
1179 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_getters.find(key);
1180 if (j != crep->m_getters.end())
1182 // the name is a data member
1183 return j->second.func(L, j->second.pointer_offset);
1186 return 0;
1189 // called from the metamethod for __newindex
1190 // obj is the object pointer
1191 static int lua_class_settable(lua_State* L)
1193 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
1194 class_rep* crep = obj->crep();
1196 #ifndef LUABIND_NO_ERROR_CHECKING
1198 if (obj->flags() & object_rep::call_super)
1200 // this block makes sure the std::string is destructed
1201 // before lua_error is called
1203 std::string msg = "derived class '";
1204 msg += crep->name();
1205 msg += "'must call super on base";
1206 lua_pushstring(L, msg.c_str());
1208 lua_error(L);
1211 #endif
1213 // we have to ignore the first argument since this may point to
1214 // a method that is not present in this class (but in a subclass)
1215 const char* key = lua_tostring(L, 2);
1216 std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_setters.find(key);
1218 if (j == crep->m_setters.end())
1220 std::map<const char*, class_rep::callback, ltstr>::iterator k = crep->m_getters.find(key);
1222 #ifndef LUABIND_NO_ERROR_CHECKING
1224 if (k != crep->m_getters.end())
1227 std::string msg = "cannot set property '";
1228 msg += crep->name();
1229 msg += ".";
1230 msg += key;
1231 msg += "', because it's read only";
1232 lua_pushstring(L, msg.c_str());
1234 lua_error(L);
1237 #endif
1239 detail::getref(L, obj->lua_table_ref());
1240 lua_replace(L, 1);
1241 lua_settable(L, 1);
1243 // assert(lua_gettop(L) == 1);
1245 else
1247 // the name is a data member
1248 j->second.func(L, j->second.pointer_offset);
1251 return 0;
1254 static int static_class_gettable(lua_State* L)
1256 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
1258 if (crep->get_class_type() == class_rep::lua_class)
1260 detail::getref(L, crep->m_table_ref);
1261 lua_pushvalue(L, 2);
1262 lua_gettable(L, -2);
1263 if (!lua_isnil(L, -1)) return 1;
1264 else lua_pop(L, 2);
1267 const char* key = lua_tostring(L, 2);
1269 std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
1270 if (i != crep->m_methods.end())
1272 // the name is a method, return it
1273 lua_pushlightuserdata(L, &i->second);
1274 lua_pushcclosure(L, class_rep::function_dispatcher, 1);
1275 return 1;
1278 #ifndef LUABIND_NO_ERROR_CHECKING
1280 std::map<const char*, int, ltstr>::const_iterator j = crep->m_static_constants.find(key);
1282 if (j != crep->m_static_constants.end())
1284 lua_pushnumber(L, j->second);
1285 return 1;
1289 std::string msg = "no static '";
1290 msg += key;
1291 msg += "' in class '";
1292 msg += crep->name();
1293 msg += "'";
1294 lua_pushstring(L, msg.c_str());
1296 lua_error(L);
1298 #endif
1300 return 0;
1303 private:
1305 // this is a pointer to the type_info structure for
1306 // this type
1307 // warning: this may be a problem when using dll:s, since
1308 // typeid() may actually return different pointers for the same
1309 // type.
1310 LUABIND_TYPE_INFO m_type;
1311 LUABIND_TYPE_INFO m_held_type;
1313 typedef void*(*extract_ptr_t)(void*);
1314 extract_ptr_t m_extract_underlying_fun;
1316 // a list of info for every class this class derives from
1317 // the information stored here is sufficient to do
1318 // type casts to the base classes
1319 std::vector<base_info> m_bases;
1321 // the class' name (as given when registered to lua with class_)
1322 #ifdef LUABIND_DONT_COPY_STRINGS
1323 const char* m_name;
1324 #else
1325 std::string m_name;
1326 #endif
1328 // contains signatures for all constructors
1329 construct_rep m_constructor;
1330 construct_rep m_wrapped_constructor;
1332 // a reference to this structure itself. Since this struct
1333 // is kept inside lua (to let lua collect it when lua_close()
1334 // is called) we need to lock it to prevent collection.
1335 // the actual reference is not currently used.
1336 int m_self_ref;
1338 // a reference to the lua table that represents this class
1339 // (only used if it is a lua class)
1340 int m_table_ref;
1342 // the type of this class.. determines if it's written in c++ or lua
1343 class_type m_class_type;
1345 // this is a lua reference that points to the lua table
1346 // that is to be used as meta table for all instances
1347 // of this class.
1348 int m_instance_metatable;
1350 // ***** the maps below contains all members in this class *****
1352 // maps method names to a structure with more
1353 // information about that method.
1354 // that struct contains the function-signatures
1355 // for every overload
1356 std::map<const char*, method_rep, ltstr> m_methods;
1358 #ifndef LUABIND_DONT_COPY_STRINGS
1359 // this is where the strings that the maps contains
1360 // pointer to are kept. To make sure they are destructed.
1361 std::vector<char*> m_strings;
1362 #endif
1364 struct callback
1366 boost::function2<int, lua_State*, int> func;
1367 int pointer_offset;
1370 // datamembers, some members may be readonly, and
1371 // only have a getter function
1372 std::map<const char*, callback, ltstr> m_getters;
1373 std::map<const char*, callback, ltstr> m_setters;
1375 struct operator_callback: public overload_rep_base
1377 inline void set_fun(int (*f)(lua_State*)) { func = f; }
1378 inline int call(lua_State* L) { return func(L); }
1379 inline void set_arity(int arity) { m_arity = arity; }
1381 private:
1383 int(*func)(lua_State*);
1386 std::vector<operator_callback> m_operators[number_of_operators]; // the operators in lua
1388 void(*m_destructor)(void*);
1390 std::map<const char*, int, ltstr> m_static_constants;
1394 inline bool is_class_rep(lua_State* L, int index)
1396 if (lua_getmetatable(L, index) == 0) return false;
1398 lua_pushstring(L, "__luabind_classrep");
1399 lua_gettable(L, -2);
1400 if (lua_toboolean(L, -1))
1402 lua_pop(L, 2);
1403 return true;
1406 lua_pop(L, 2);
1407 return false;
1413 #endif // LUABIND_CLASS_REP_HPP_INCLUDED