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

📄 class_rep.cpp

📁 魔兽世界的私服源程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			lua_error(L);
		}

			// TODO: should this be a warning or something?
/*
			// since the derived class is a lua class
			// it may have reimplemented virtual functions
			// therefore, we have to instantiate the Basewrapper
			// if there is no basewrapper, throw a run-time error
			if (!rep->overloads[match_index].has_wrapped_construct())
			{
				{
					std::string msg = "Cannot derive from C++ class '";
					msg += base->name();
					msg += "'. It does not have a wrapped type";
					lua_pushstring(L, msg.c_str());
				}
				lua_error(L);
			}
*/
#endif

#ifndef LUABIND_NO_EXCEPTIONS

		try
		{

#endif

			if (!rep->overloads[match_index].has_wrapped_construct())
			{
				// if the type doesn't have a wrapped type, use the ordinary constructor
				obj->set_object(rep->overloads[match_index].construct(L));
			}
			else
			{
				// get reference to lua object
				lua_pushvalue(L, lua_upvalueindex(2));
				int ref = detail::ref(L);
				obj->set_object(rep->overloads[match_index].construct_wrapped(L, ref));
			}
			// TODO: is the wrapped type destructed correctly?
			// it should, since the destructor is either the wrapped type's
			// destructor or the base type's destructor, depending on wether
			// the type has a wrapped type or not.
			obj->set_destructor(base->destructor());
			return 0;

#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 = base->m_name;
			msg += "() threw an exception";
			lua_pushstring(L, msg.c_str());
		}
		// can only be reached if an exception was thrown
		lua_error(L);
#endif
	}

	return 0;

}



 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L)
{
	class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
	detail::getref(L, crep->m_table_ref);
	lua_replace(L, 1);
	lua_rawset(L, -3);

	crep->m_operator_cache = 0; // invalidate cache
	
	return 0;
}

 int luabind::detail::class_rep::construct_lua_class_callback(lua_State* L)
{
	class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));

	int args = lua_gettop(L);

	// lua stack: crep <arguments>

	lua_newtable(L);
	int ref = detail::ref(L);

	bool has_bases = !crep->bases().empty();
		
	if (has_bases)
	{
		lua_pushstring(L, "super");
		lua_pushvalue(L, 1); // crep
	}

	// lua stack: crep <arguments> "super" crep
	// or
	// lua stack: crep <arguments>

	// if we have a baseclass we set the flag to say that the super has not yet been called
	// we will use this flag later to check that it actually was called from __init()
	int flags = object_rep::lua_class | object_rep::owner | (has_bases ? object_rep::call_super : 0);

	void* obj_ptr = lua_newuserdata(L, sizeof(object_rep));
	new(obj_ptr) object_rep(crep, flags, ref);

	detail::getref(L, crep->metatable_ref());
	lua_setmetatable(L, -2);

	// lua stack: crep <arguments> "super" crep obj_ptr
	// or
	// lua stack: crep <arguments> obj_ptr

	if (has_bases)	lua_pushvalue(L, -1); // obj_ptr
	lua_replace(L, 1); // obj_ptr

	// lua stack: obj_ptr <arguments> "super" crep obj_ptr
	// or
	// lua stack: obj_ptr <arguments>

	if (has_bases)
	{
		lua_pushcclosure(L, super_callback, 2);
		// lua stack: crep <arguments> "super" function
		lua_settable(L, LUA_GLOBALSINDEX);
	}

	// lua stack: crep <arguments>

	lua_pushvalue(L, 1);
	lua_insert(L, 1);

	detail::getref(L, crep->table_ref());
	lua_pushstring(L, "__init");
	lua_gettable(L, -2);

#ifndef LUABIND_NO_ERROR_CHECKING

	// TODO: should this be a run-time error?
	// maybe the default behavior should be to just call
	// the base calss' constructor. We should register
	// the super callback funktion as __init
	if (!lua_isfunction(L, -1))
	{
		{
			std::string msg = crep->name();
			msg += ":__init is not defined";
			lua_pushstring(L, msg.c_str());
		}
		lua_error(L);
	}

#endif

	lua_insert(L, 2); // function first on stack
	lua_pop(L, 1);
	// TODO: lua_call may invoke longjump! make sure we don't have any memory leaks!
	// we don't have any stack objects here
	lua_call(L, args, 0);

#ifndef LUABIND_NO_ERROR_CHECKING

	object_rep* obj = static_cast<object_rep*>(obj_ptr);
	if (obj->flags() & object_rep::call_super)
	{
		lua_pushstring(L, "derived class must call super on base");
		lua_error(L);
	}

#endif

	return 1;
}

// called from the metamethod for __index
// obj is the object pointer
 int luabind::detail::class_rep::lua_class_gettable(lua_State* L)
{
	object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
	class_rep* crep = obj->crep();

#ifndef LUABIND_NO_ERROR_CHECKING

	if (obj->flags() & object_rep::call_super)
	{
		lua_pushstring(L, "derived class must call super on base");
		lua_error(L);
	}

#endif

	// we have to ignore the first argument since this may point to
	// a method that is not present in this class (but in a subclass)
	const char* key = lua_tostring(L, 2);

	if (key && !strcmp(key, "__ok"))
	{
		class_rep* crep = obj->crep();

		void* p = crep->extractor() ? crep->extractor()(obj->ptr())
			: obj->ptr();

		lua_pushboolean(L, p != 0);
		return 1;
	}
	
	detail::getref(L, obj->lua_table_ref());
	lua_pushvalue(L, 2);
	lua_gettable(L, -2);

	if (!lua_isnil(L, -1)) 
	{
		lua_remove(L, -2); // remove table
		return 1;
	}

	lua_pop(L, 2);

	detail::getref(L, crep->table_ref());
	lua_pushvalue(L, 2);
	lua_gettable(L, -2);

	if (!lua_isnil(L, -1)) 
	{
		lua_remove(L, -2); // more table
		return 1;
	}

	lua_pop(L, 2);

	if (lua_isnil(L, 2))
	{
		lua_pushnil(L);
		return 1;
	}

	std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
	if (i != crep->m_methods.end())
	{
		// the name is a method, return it
		lua_pushlightuserdata(L, &i->second);
		lua_pushcclosure(L, class_rep::function_dispatcher, 1);
		return 1;
	}

	std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_getters.find(key);
	if (j != crep->m_getters.end())
	{
		// the name is a data member
		return j->second.func(L, j->second.pointer_offset);
	}

	lua_pushnil(L);
	return 1;
}

// called from the metamethod for __newindex
// obj is the object pointer
 int luabind::detail::class_rep::lua_class_settable(lua_State* L)
{
	object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
	class_rep* crep = obj->crep();

#ifndef LUABIND_NO_ERROR_CHECKING

	if (obj->flags() & object_rep::call_super)
	{
		// this block makes sure the std::string is destructed
		// before lua_error is called
		{
			std::string msg = "derived class '";
			msg += crep->name();
			msg += "'must call super on base";
			lua_pushstring(L, msg.c_str());
		}
		lua_error(L);
	}

#endif

	// we have to ignore the first argument since this may point to
	// a method that is not present in this class (but in a subclass)
	const char* key = lua_tostring(L, 2);
	std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_setters.find(key);

	if (j == crep->m_setters.end())
	{
		std::map<const char*, class_rep::callback, ltstr>::iterator k = crep->m_getters.find(key);

#ifndef LUABIND_NO_ERROR_CHECKING

		if (k != crep->m_getters.end())
		{
			{
				std::string msg = "cannot set property '";
				msg += crep->name();
				msg += ".";
				msg += key;
				msg += "', because it's read only";
				lua_pushstring(L, msg.c_str());
			}
			lua_error(L);
		}

#endif

		detail::getref(L, obj->lua_table_ref());
		lua_replace(L, 1);
		lua_settable(L, 1);
	}
	else
	{
		// the name is a data member
		j->second.func(L, j->second.pointer_offset);
	}

	return 0;
}

 int luabind::detail::class_rep::static_class_gettable(lua_State* L)
{
	class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));

	if (crep->get_class_type() == class_rep::lua_class)
	{
		detail::getref(L, crep->m_table_ref);
		lua_pushvalue(L, 2);
		lua_gettable(L, -2);
		if (!lua_isnil(L, -1)) return 1;
		else lua_pop(L, 2);
	}

	const char* key = lua_tostring(L, 2);

	std::map<const char*, method_rep, ltstr>::iterator i = crep->m_methods.find(key);
	if (i != crep->m_methods.end())
	{
		// the name is a method, return it
		lua_pushlightuserdata(L, &i->second);
		lua_pushcclosure(L, class_rep::function_dispatcher, 1);
		return 1;
	}

#ifndef LUABIND_NO_ERROR_CHECKING

	std::map<const char*, int, ltstr>::const_iterator j = crep->m_static_constants.find(key);

	if (j != crep->m_static_constants.end())
	{
		lua_pushnumber(L, j->second);
		return 1;
	}

	{
		std::string msg = "no static '";
		msg += key;
		msg += "' in class '";
		msg += crep->name();
		msg += "'";
		lua_pushstring(L, msg.c_str());
	}
	lua_error(L);

#endif

	return 0;
}

bool luabind::detail::is_class_rep(lua_State* L, int index)
{
	if (lua_getmetatable(L, index) == 0) return false;

	lua_pushstring(L, "__luabind_classrep");
	lua_gettable(L, -2);
	if (lua_toboolean(L, -1))
	{
		lua_pop(L, 2);
		return true;
	}

	lua_pop(L, 2);
	return false;
}

void luabind::detail::finalize(lua_State* L, class_rep* crep)
{
	if (crep->get_class_type() != class_rep::lua_class) return;

	detail::getref(L, crep->table_ref());
	lua_pushstring(L, "__finalize");
	lua_gettable(L, -2);

	if (lua_isnil(L, -1))
	{
		lua_pop(L, 1);
	}
	else
	{
		lua_pushvalue(L, -2);
		lua_call(L, 1, 0);
	}

	for (std::vector<class_rep::base_info>::const_iterator 
			i = crep->bases().begin(); i != crep->bases().end(); ++i)
	{
		if (i->base) finalize(L, i->base);
	}
}

void* luabind::detail::class_rep::convert_to(LUABIND_TYPE_INFO target_type, const object_rep* obj, void* target_memory) const
{
	// TODO: since this is a member function, we don't have to use the accesor functions for
	// the types and the extractor

	int steps = 0;
	int offset = 0;
	if (!(LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), target_type))
		&& !(LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), target_type)))
	{
		steps = implicit_cast(this, target_type, offset);
	}

	// should never be called with a type that can't be cast
	assert((steps >= 0) && "internal error, please report");

	if (LUABIND_TYPE_INFO_EQUAL(target_type, holder_type()))
	{
		// if the type we are trying to convert to is the holder_type
		// it means that his crep has a holder_type (since it would have
		// been invalid otherwise, and T cannot be invalid). It also means
		// that we need no conversion, since the holder_type is what the
		// object points to.
		return obj->ptr();
	}

	if (LUABIND_TYPE_INFO_EQUAL(target_type, const_holder_type()))
	{
		if (obj->flags() & object_rep::constant)
		{
			// we are holding a constant
			return obj->ptr();
		}
		else
		{
			// we are holding a non-constant, we need to convert it
			// to a const_holder.
			m_const_converter(obj->ptr(), target_memory);
			return target_memory;
		}
	}

	void* raw_pointer;

	if (has_holder())
	{
		// this means that we have a holder type where the
		// raw-pointer needs to be extracted
		raw_pointer = extractor()(obj->ptr());
	}
	else
	{
		raw_pointer = obj->ptr();
	}

	return static_cast<char*>(raw_pointer) + offset;
}

void class_rep::cache_operators(lua_State* L)
{
	m_operator_cache = 0x1;

	for (int i = 0; i < number_of_operators; ++i)
	{
		getref(L, table_ref());
		lua_pushstring(L, get_operator_name(i));
		lua_rawget(L, -2);

		if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1);

		lua_pop(L, 2);
	}
}

bool class_rep::has_operator_in_lua(lua_State* L, int id)
{
	if ((m_operator_cache & 0x1) == 0)
		cache_operators(L);

	const int mask = 1 << (id + 1);

	return m_operator_cache & mask;
}

⌨️ 快捷键说明

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