class_rep.cpp.svn-base

来自「本人找过多个在linux下c++的lua5.1封装库,但很少.luabind已经」· SVN-BASE 代码 · 共 1,676 行 · 第 1/3 页

SVN-BASE
1,676
字号
// Copyright (c) 2003 Daniel Wallin and Arvid Norberg// Permission is hereby granted, free of charge, to any person obtaining a// copy of this software and associated documentation files (the "Software"),// to deal in the Software without restriction, including without limitation// the rights to use, copy, modify, merge, publish, distribute, sublicense,// and/or sell copies of the Software, and to permit persons to whom the// Software is furnished to do so, subject to the following conditions:// The above copyright notice and this permission notice shall be included// in all copies or substantial portions of the Software.// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE// OR OTHER DEALINGS IN THE SOFTWARE.#include <luabind/lua_include.hpp>#include <luabind/detail/stack_utils.hpp>#include <luabind/luabind.hpp>#include <utility>using namespace luabind::detail;namespace luabind { namespace detail{	struct method_name	{		method_name(char const* n): name(n) {}		bool operator()(method_rep const& o) const		{ return std::strcmp(o.name, name) == 0; }		char const* name;	};}}#ifndef LUABIND_NO_ERROR_CHECKING	std::string luabind::detail::get_overload_signatures_candidates(			lua_State* L			, std::vector<const overload_rep_base*>::iterator start			, std::vector<const overload_rep_base*>::iterator end			, std::string name)	{		std::string s;		for (; start != end; ++start)		{			s += name;			(*start)->get_signature(L, s);			s += "\n";		}		return s;	}#endifluabind::detail::class_rep::class_rep(LUABIND_TYPE_INFO type	, const char* name	, lua_State* L	,  void(*destructor)(void*)	,  void(*const_holder_destructor)(void*)	, LUABIND_TYPE_INFO holder_type	, LUABIND_TYPE_INFO const_holder_type	, void*(*extractor)(void*)	, const void*(*const_extractor)(void*)	, void(*const_converter)(void*,void*)	, void(*construct_holder)(void*,void*)	, void(*construct_const_holder)(void*,void*)	, void(*default_construct_holder)(void*)	, void(*default_construct_const_holder)(void*)	, void(*adopt_fun)(void*)	, int holder_size	, int holder_alignment)	: m_type(type)	, m_holder_type(holder_type)	, m_const_holder_type(const_holder_type)	, m_extractor(extractor)	, m_const_extractor(const_extractor)	, m_const_converter(const_converter)	, m_construct_holder(construct_holder)	, m_construct_const_holder(construct_const_holder)	, m_default_construct_holder(default_construct_holder)	, m_default_construct_const_holder(default_construct_const_holder)	, m_adopt_fun(adopt_fun)	, m_holder_size(holder_size)	, m_holder_alignment(holder_alignment)	, m_name(name)	, m_class_type(cpp_class)	, m_destructor(destructor)	, m_const_holder_destructor(const_holder_destructor)	, m_operator_cache(0){	assert(m_holder_alignment >= 1 && "internal error");	lua_newtable(L);	handle(L, -1).swap(m_table);	lua_newtable(L);	handle(L, -1).swap(m_default_table);	lua_pop(L, 2);	class_registry* r = class_registry::get_registry(L);	assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");	detail::getref(L, r->cpp_class());	lua_setmetatable(L, -2);	lua_pushvalue(L, -1); // duplicate our user data	m_self_ref.set(L);	m_instance_metatable = r->cpp_instance();}luabind::detail::class_rep::class_rep(lua_State* L, const char* name)	: m_type(LUABIND_INVALID_TYPE_INFO)	, m_holder_type(LUABIND_INVALID_TYPE_INFO)	, m_const_holder_type(LUABIND_INVALID_TYPE_INFO)	, m_extractor(0)	, m_const_extractor(0)	, m_const_converter(0)	, m_construct_holder(0)	, m_construct_const_holder(0)	, m_default_construct_holder(0)	, m_default_construct_const_holder(0)	, m_adopt_fun(0)	, m_holder_size(0)	, m_holder_alignment(1)	, m_name(name)	, m_class_type(lua_class)	, m_destructor(0)	, m_const_holder_destructor(0)	, m_operator_cache(0){	lua_newtable(L);	handle(L, -1).swap(m_table);	lua_newtable(L);	handle(L, -1).swap(m_default_table);	lua_pop(L, 2);	class_registry* r = class_registry::get_registry(L);	assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");	detail::getref(L, r->lua_class());	lua_setmetatable(L, -2);	lua_pushvalue(L, -1); // duplicate our user data	m_self_ref.set(L);	m_instance_metatable = r->lua_instance();}luabind::detail::class_rep::~class_rep(){}// leaves object on lua stackstd::pair<void*,void*> luabind::detail::class_rep::allocate(lua_State* L) const{	const int overlap = sizeof(object_rep)&(m_holder_alignment-1);	const int padding = overlap==0?0:m_holder_alignment-overlap;	const int size = sizeof(object_rep) + padding + m_holder_size;	char* mem = static_cast<char*>(lua_newuserdata(L, size));	char* ptr = mem + sizeof(object_rep) + padding;	return std::pair<void*,void*>(mem,ptr);}/*#include <iostream>namespace{	void dump_stack(lua_State* L)	{		for (int i = 1; i <= lua_gettop(L); ++i)		{			int t = lua_type(L, i);			switch (t)			{			case LUA_TNUMBER:				std::cout << "[" << i << "] number: " << lua_tonumber(L, i) << "\n";				break;			case LUA_TSTRING:				std::cout << "[" << i << "] string: " << lua_tostring(L, i) << "\n";				break;			case LUA_TUSERDATA:				std::cout << "[" << i << "] userdata: " << lua_touserdata(L, i) << "\n";				break;			case LUA_TTABLE:				std::cout << "[" << i << "] table:\n";				break;			case LUA_TNIL:				std::cout << "[" << i << "] nil:\n";				break;			}		}	}}*/void luabind::detail::class_rep::adopt(bool const_obj, void* obj){	if (m_adopt_fun == 0) return;	if (m_extractor)	{		assert(m_const_extractor);		if (const_obj)			m_adopt_fun(const_cast<void*>(m_const_extractor(obj)));		else			m_adopt_fun(m_extractor(obj));	}	else	{		m_adopt_fun(obj);	}}// lua stack: userdata, keyint luabind::detail::class_rep::gettable(lua_State* L){	// if key is nil, return nil	if (lua_isnil(L, 2))	{		lua_pushnil(L);		return 1;	}	object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));	// 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);#ifndef LUABIND_NO_ERROR_CHECKING	if (std::strlen(key) != lua_strlen(L, 2))	{		{			std::string msg("luabind does not support "				"member names with extra nulls:\n");			msg += std::string(lua_tostring(L, 2), lua_strlen(L, 2));			lua_pushstring(L, msg.c_str());		}		lua_error(L);	}#endif	// special case to see if this is a null-pointer	if (key && !std::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;	}// First, look in the instance's table	detail::lua_reference const& tbl = obj->get_lua_table();	if (tbl.is_valid())	{		tbl.get(L);		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);	}// Then look in the class' table for this member	obj->crep()->get_table(L);	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);	std::map<const char*, callback, ltstr>::iterator j = m_getters.find(key);	if (j != 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// the object pointer is passed on the lua stack// lua stack: userdata, key, valuebool luabind::detail::class_rep::settable(lua_State* L){	// if the key is 'nil' fail	if (lua_isnil(L, 2)) return false;	// 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 (std::strlen(key) == lua_strlen(L, 2))	{		std::map<const char*, callback, ltstr>::iterator j = m_setters.find(key);		if (j != m_setters.end())		{			// the name is a data member#ifndef LUABIND_NO_ERROR_CHECKING			if (j->second.match(L, 3) < 0)			{				std::string msg("the attribute '");				msg += m_name;				msg += ".";				msg += key;				msg += "' is of type: ";				j->second.sig(L, msg);				msg += "\nand does not match: (";				msg += stack_content_by_name(L, 3);				msg += ")";				lua_pushstring(L, msg.c_str());				return false;			}#endif			j->second.func(L, j->second.pointer_offset);			return true;		}		if (m_getters.find(key) != m_getters.end())		{			// this means that we have a getter but no			// setter for an attribute. We will then fail			// because that attribute is read-only			std::string msg("the attribute '");			msg += m_name;			msg += ".";			msg += key;			msg += "' is read only";			lua_pushstring(L, msg.c_str());			return false;		}	}	// set the attribute to the object's table	object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));	detail::lua_reference& tbl = obj->get_lua_table();	if (!tbl.is_valid())	{		// this is the first time we are trying to add		// a member to this instance, create the table.		lua_newtable(L);		lua_pushvalue(L, -1);		tbl.set(L);	}	else	{		tbl.get(L);	}	lua_pushvalue(L, 2);	lua_pushvalue(L, 3);	lua_settable(L, 4);	lua_pop(L, 3);	return true;}int class_rep::gettable_dispatcher(lua_State* L){	object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));	return obj->crep()->gettable(L);}// this is called as __newindex metamethod on every instance of this classint luabind::detail::class_rep::settable_dispatcher(lua_State* L){	object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));	bool success = obj->crep()->settable(L);#ifndef LUABIND_NO_ERROR_CHECKING	if (!success)	{		// class_rep::settable() will leave		// error message on the stack in case		// of failure		lua_error(L);	}#endif	return 0;}int luabind::detail::class_rep::operator_dispatcher(lua_State* L){	for (int i = 0; i < 2; ++i)	{		if (is_class_object(L, 1 + i))		{            int nargs = lua_gettop(L);            lua_pushvalue(L, lua_upvalueindex(1));			lua_gettable(L, 1 + i);			if (lua_isnil(L, -1))			{				lua_pop(L, 1);				continue;			}			lua_insert(L, 1); // move the function to the bottom            nargs = lua_toboolean(L, lua_upvalueindex(2)) ? 1 : nargs;            if (lua_toboolean(L, lua_upvalueindex(2))) // remove trailing nil                lua_remove(L, 3);            lua_call(L, nargs, 1);            return 1;		}	}	lua_pop(L, lua_gettop(L));	lua_pushstring(L, "No such operator defined");	lua_error(L);	return 0;}// this is called as metamethod __call on the class_rep.int luabind::detail::class_rep::constructor_dispatcher(lua_State* L){	class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));	construct_rep* rep = &crep->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.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);#ifdef LUABIND_NO_ERROR_CHECKING	}#else	if (!found)	{		{			std::string msg("no constructor of '");			msg += crep->name();			msg += "' matched the arguments (";			msg += stack_content_by_name(L, 2);			msg += ")\n candidates are:\n";			msg += get_overload_signatures(L, rep->overloads.begin(), rep->overloads.end(), crep->name());			lua_pushstring(L, msg.c_str());		}		lua_error(L);	}	else if (ambiguous)	{		{			std::string msg("call of overloaded constructor '");			msg += crep->m_name;			msg +=  "(";			msg += stack_content_by_name(L, 2);			msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";			std::vector<const overload_rep_base*> candidates;			find_exact_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), min_match, num_params, candidates);			msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), crep->name());			lua_pushstring(L, msg.c_str());		}		lua_error(L);	}#endif#ifndef LUABIND_NO_EXCEPTIONS	try	{#endif		void* obj_rep;		void* held;		boost::tie(obj_rep,held) = crep->allocate(L);		weak_ref backref(L, -1);		void* object_ptr = rep->overloads[match_index].construct(L, backref);		if (crep->has_holder())		{			crep->m_construct_holder(held, object_ptr);			object_ptr = held;		}		new(obj_rep) object_rep(object_ptr, crep, object_rep::owner, crep->destructor());		detail::getref(L, crep->m_instance_metatable);		lua_setmetatable(L, -2);		return 1;#ifndef LUABIND_NO_EXCEPTIONS	}        catch(const error&)    {    }	catch(const std::exception& e)	{		lua_pushstring(L, e.what());	}	catch(const char* s)	{		lua_pushstring(L, s);	}	catch(...)	{		{			std::string msg = crep->name();			msg += "() threw an exception";			lua_pushstring(L, msg.c_str());		}

⌨️ 快捷键说明

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