⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 class_rep_scope.hpp

📁 魔兽世界的私服源程序
💻 HPP
📖 第 1 页 / 共 3 页
字号:
					std::string msg = crep->name();
					msg += "() threw an exception";
					lua_pushstring(L, msg.c_str());
				}
			}

			// we can only reach this line if an exception was thrown
			lua_error(L);
			return 0; // will never be reached

#endif

		}

		static int implicit_cast(const class_rep* from, const class_rep* to, int& pointer_offset)
		{
			int offset = 0;
			if (LUABIND_TYPE_INFO_EQUAL(from->type(), to->type())) return 0;

			for (std::vector<class_rep::base_info>::const_iterator i = from->bases().begin(); i != from->bases().end(); ++i)
			{
				int steps = implicit_cast(i->base, to, offset);
				pointer_offset = offset + i->pointer_offset;
				if (steps >= 0) return steps + 2;
			}
			return -1;
		}

		// the functions dispatcher assumes the following:
		// there is one upvalue that points to the method_rep that this dispatcher is to call
		// the first parameter on the lua stack is an object_rep that points to the object the
		// call is being made on
		static int function_dispatcher(lua_State* L)
		{
			method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
			object_rep* obj = reinterpret_cast<object_rep*>(lua_touserdata(L, 1));

#ifndef LUABIND_NO_ERROR_CHECKING

			if (is_class_object(L, 1) == 0)
			{
				{
					std::string msg = "No self reference given as first parameter to member function '";
					msg += rep->crep->name();
					msg += ":";
					msg += rep->name;
					msg += "'. Have you used '.' instead of ':'?";

					lua_pushstring(L, msg.c_str());
				}
				lua_error(L);
			}

			int p;
			if (implicit_cast(obj->crep(), rep->crep, p) < 0)
			{
				{
					std::string msg = "invalid self reference given to '";
					msg += rep->crep->name();
					msg += ":";
					msg += rep->name;
					msg += "'";
					lua_pushstring(L, msg.c_str());
				}
				lua_error(L);
			}

#endif

			bool ambiguous = false;
			int match_index = -1;
			int min_match = std::numeric_limits<int>::max();
			bool found;

#ifdef LUABIND_NO_ERROR_CHECKING
			if (rep->overloads().size() == 1)
			{
				match_index = 0;
			}
			else
			{
#endif

				int num_params = lua_gettop(L) - 1;
				found = find_best_match(L, rep->overloads().begin(), rep->overloads().end(), ambiguous, min_match, match_index, num_params);

#ifdef LUABIND_NO_ERROR_CHECKING

			}

#else

			if (!found)
			{
				{
					std::string msg = "no overload of  '";
					msg += rep->crep->name();
					msg += ":";
					msg += rep->name;
					msg += "' matched the arguments (";
					msg += stack_content_by_name(L, 2);
					msg += ")\ncandidates are:\n";

					std::string function_name;
					function_name += rep->crep->name();
					function_name += ":";
					function_name += rep->name;

					msg += get_overload_signatures(L, rep->overloads().begin(), rep->overloads().end(), function_name);

					lua_pushstring(L, msg.c_str());
				}
				lua_error(L);
			}
			else if (ambiguous)
			{
				{
					std::string msg = "call of overloaded  '";
					msg += rep->crep->name();
					msg += ":";
					msg += rep->name;
					msg += "(";
					msg += stack_content_by_name(L, 2);
					msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";

					std::vector<overload_rep> candidates;
					find_exact_match(L, rep->overloads().begin(), rep->overloads().end(), min_match, num_params, candidates);

					std::string function_name;
					function_name += rep->crep->name();
					function_name += ":";
					function_name += rep->name;

					msg += get_overload_signatures(L, candidates.begin(), candidates.end(), function_name);

					lua_pushstring(L, msg.c_str());
				}
				lua_error(L);
			}

#endif

#ifndef LUABIND_NO_EXCEPTIONS

			try
			{

#endif

				const overload_rep& o = rep->overloads()[match_index];
				return o.call(L, *obj);

#ifndef LUABIND_NO_EXCEPTIONS

			}
			catch(const std::exception& e)
			{
				lua_pushstring(L, e.what());
			}
			catch (const char* s)
			{
				lua_pushstring(L, s);
			}
			catch(...)
			{
				std::string msg = rep->crep->name();
				msg += ":";
				msg += rep->name;
				msg += "() threw an exception";
				lua_pushstring(L, msg.c_str());
			}
			// we can only reach this line if an exception was thrown
			lua_error(L);
			return 0; // will never be reached

#endif
			
		}






		struct base_info
		{
			int pointer_offset; // the offset added to the pointer to obtain a basepointer (due to multiple-inheritance)
			class_rep* base;
		};


		inline void add_base_class(const base_info& binfo)
		{
			// If you hit this assert you are deriving from a type that is not registered
			// in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
			// Please note that if you don't need to have access to the base class or the
			// conversion from the derived class to the base class, you don't need
			// to tell luabind that it derives.
			assert(binfo.base && "You cannot derive from an unregistered type");

			class_rep* bcrep = binfo.base;

			// import all functions from the base
			for (std::map<const char*, method_rep, ltstr>::const_iterator i = bcrep->m_methods.begin(); i != bcrep->m_methods.end(); ++i)
			{
#ifndef LUABIND_DONT_COPY_STRINGS
				m_strings.push_back(dup_string(i->first));
				method_rep& m = m_methods[m_strings.back()];
#else
				method_rep& m = m_methods[i->first];
#endif
				m.name = i->first;
				m.crep = this;

				for (std::vector<overload_rep>::const_iterator j = i->second.overloads().begin(); j != i->second.overloads().end(); ++j)
				{
					overload_rep o = *j;
					o.add_offset(binfo.pointer_offset);
					m.add_overload(o);
				}
			}

			// import all getters from the base
			for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_getters.begin(); i != bcrep->m_getters.end(); ++i)
			{
#ifndef LUABIND_DONT_COPY_STRINGS
				m_strings.push_back(dup_string(i->first));
				callback& m = m_getters[m_strings.back()];
#else
				callback& m = m_getters[i->first];
#endif
				m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
				m.func = i->second.func;
			}

			// import all setters from the base
			for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_setters.begin(); i != bcrep->m_setters.end(); ++i)
			{
#ifndef LUABIND_DONT_COPY_STRINGS
				// TODO: optimize this by not copying the string if it already exists in m_setters.
				// This goes for m_getters, m_static_constants and m_functions too. Both here
				// in add_base() and in the add_function(), add_getter() ... functions.
				m_strings.push_back(dup_string(i->first));
				callback& m = m_setters[m_strings.back()];
#else
				callback& m = m_setters[i->first];
#endif
				m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
				m.func = i->second.func;
			}

			// import all static constants
			for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin(); i != bcrep->m_static_constants.end(); ++i)
			{
#ifndef LUABIND_DONT_COPY_STRINGS
				m_strings.push_back(dup_string(i->first));
				int& v = m_static_constants[m_strings.back()];
#else
				int& v = m_static_constants[i->first];
#endif
				v = i->second;
			}

			// import all operators
			for (int i = 0; i < number_of_operators; ++i)
			{
				for (std::vector<operator_callback>::const_iterator j = bcrep->m_operators[i].begin(); j != bcrep->m_operators[i].end(); ++j)
					m_operators[i].push_back(*j);
			}

			// also, save the baseclass info to be used for typecasts
			m_bases.push_back(binfo);
		}


		inline const std::vector<base_info>& bases() const throw() { return m_bases; }
		inline LUABIND_TYPE_INFO type() const throw() { return m_type; }
		inline void set_type(LUABIND_TYPE_INFO t) { m_type = t; }

		inline void add_function(const char* name, const overload_rep& o)
		{

#ifdef LUABIND_DONT_COPY_STRINGS
			detail::method_rep& method = m_methods[name];
			method.name = name;
#else
			m_strings.push_back(dup_string(name));
			detail::method_rep& method = m_methods[m_strings.back()];
			method.name = m_strings.back();
#endif

			method.add_overload(o);
			method.crep = this;
		}

		inline void add_constructor(const detail::construct_rep::overload_t& o)
		{
			m_constructor.overloads.push_back(o);
		}

		inline void add_wrapped_constructor(const detail::construct_rep::overload_t& o)
		{
			m_wrapped_constructor.overloads.push_back(o);
		}

		inline const char* name() const throw()
		{
#ifdef LUABIND_DONT_COPY_STRINGS
			return m_name;
#else
			return m_name.c_str();
#endif
		}

		inline void add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
		{
			callback c;
			c.func = g;
			c.pointer_offset = 0;
#ifndef LUABIND_DONT_COPY_STRINGS
			m_strings.push_back(dup_string(name));
			m_getters[m_strings.back()] = c;
#else
			m_getters[name] = c;
#endif
		}

		inline void add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
		{
			callback c;
			c.func = s;
			c.pointer_offset = 0;
#ifndef LUABIND_DONT_COPY_STRINGS
			m_strings.push_back(dup_string(name));
			m_setters[m_strings.back()] = c;
#else
			m_setters[name] = c;
#endif
		}

#ifndef LUABIND_NO_ERROR_CHECKING
		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)
#else
		inline void add_operator(lua_State*, int op_id,  int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
#endif
		{
			operator_callback o;
			o.set_fun(func);
			o.set_match_fun(matcher);
			o.set_arity(arity);

#ifndef LUABIND_NO_ERROR_CHECKING

			o.set_sig_fun(sig);

#endif
			m_operators[op_id].push_back(o);
		}
		
		// the lua reference to this class_rep
		inline int self_ref() const throw() { return m_self_ref; }

		// the lua reference to the metatable for this class' instances
		inline int metatable_ref() const throw() { return m_instance_metatable; }

		inline int table_ref() const { return m_table_ref; }

		inline void(*destructor() const)(void*) { return m_destructor; }

		inline class_type get_class_type() const { return m_class_type; }

		void add_static_constant(const char* name, int val)
		{
#ifndef LUABIND_DONT_COPY_STRINGS
			m_strings.push_back(dup_string(name));
			m_static_constants[m_strings.back()] = val;
#else
			m_static_constants[name] = val;
#endif
		}

	static inline int super_callback(lua_State* L)
	{
		int args = lua_gettop(L);
		
		object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, lua_upvalueindex(2)));
		class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
		class_rep* base = crep->bases()[0].base;

//		std::cout << "__super of " << base->name() << "\n";

		if (base->get_class_type() == class_rep::lua_class)
		{
			if (base->bases().empty())
			{
				obj->set_flags(obj->flags() & ~object_rep::call_super);

				lua_pushstring(L, "super");
				lua_pushnil(L);
				lua_settable(L, LUA_GLOBALSINDEX);
			}
			else
			{
				lua_pushstring(L, "super");
				lua_pushlightuserdata(L, base);
				lua_pushvalue(L, lua_upvalueindex(2));
				lua_pushcclosure(L, super_callback, 2);
				lua_settable(L, LUA_GLOBALSINDEX);
			}

//			std::cout << "  lua_class\n";
			detail::getref(L, base->table_ref());
			lua_pushstring(L, "__init");
			lua_gettable(L, -2);
			lua_insert(L, 1);
			lua_pop(L, 1);

			lua_pushvalue(L, lua_upvalueindex(2));
			lua_insert(L, 2);

			lua_call(L, args + 1, 0);

			// TODO: instead of clearing the global variable "super"
			// store it temporarily in the registry. maybe we should
			// have some kind of warning if the super global is used?
			lua_pushstring(L, "super");
			lua_pushnil(L);
			lua_settable(L, LUA_GLOBALSINDEX);
		}
		else
		{
			obj->set_flags(obj->flags() & ~object_rep::call_super);
//			std::cout << "  cpp_class\n";

			// we need to push some garbage at index 1 to make the construction work
			lua_pushboolean(L, 1);
			lua_insert(L, 1);

			construct_rep* rep = &base->m_constructor;

			bool ambiguous = false;
			int match_index = -1;
			int min_match = std::numeric_limits<int>::max();
			bool found;
			
#ifdef LUABIND_NO_ERROR_CHECKING

			if (rep->overloads.size() == 1)
			{
				match_index = 0;
			}
			else
			{

#endif

				int num_params = lua_gettop(L) - 1;
				found = find_best_match(L, rep->overloads.begin(), rep->overloads.end(), ambiguous, min_match, match_index, num_params);

#ifdef LUABIND_NO_ERROR_CHECKING

			}

#else
				
			if (!found)
			{
				{
					std::string msg = "no constructor of '";
					msg += base->m_name;
					msg += "' matched the arguments (";
					msg += stack_content_by_name(L, 2);
					msg += ")";
					lua_pushstring(L, msg.c_str());
				}
				lua_error(L);
			}
			else if (ambiguous)
			{
				{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -