class_rep.cpp.svn-base
来自「本人找过多个在linux下c++的lua5.1封装库,但很少.luabind已经」· SVN-BASE 代码 · 共 1,676 行 · 第 1/3 页
SVN-BASE
1,676 行
} // we can only reach this line if an exception was thrown lua_error(L); return 0; // will never be reached#endif}/* the functions dispatcher assumes the following: upvalues: 1: method_rep* method, points to the method_rep that this dispatcher is to call 2: boolean force_static, is true if this is to be a static call and false if it is a normal call (= virtual if possible). stack: 1: object_rep* self, points to the object the call is being made on*/int luabind::detail::class_rep::function_dispatcher(lua_State* L){#ifndef NDEBUG/* lua_Debug tmp_; assert(lua_getinfo(L, "u", &tmp_)); assert(tmp_.nups == 2);*/ assert(lua_type(L, lua_upvalueindex(1)) == LUA_TLIGHTUSERDATA); assert(lua_type(L, lua_upvalueindex(2)) == LUA_TBOOLEAN); assert(lua_type(L, lua_upvalueindex(3)) == LUA_TLIGHTUSERDATA); assert(lua_touserdata(L, lua_upvalueindex(3)) == reinterpret_cast<void*>(0x1337));// assert(lua_type(L, 1) == LUA_TUSERDATA);#endif method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1))); int force_static_call = lua_toboolean(L, lua_upvalueindex(2)); 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(overload_rep), 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, 1); 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, 1); 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(overload_rep), min_match, num_params, candidates); std::string function_name; function_name += rep->crep->name(); function_name += ":"; function_name += rep->name; msg += get_overload_signatures_candidates(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]; if (force_static_call && !o.has_static()) { lua_pushstring(L, "pure virtual function called"); } else { return o.call(L, force_static_call != 0); }#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 = rep->crep->name(); msg += ":"; msg += rep->name; msg += "() threw an exception"; lua_pushstring(L, msg.c_str()); }#endif // we can only reach this line if an error occured lua_error(L); return 0; // will never be reached}#ifndef NDEBUG#ifndef BOOST_NO_STRINGSTREAM#include <sstream>#else#include <strstream>#endifnamespace{ std::string to_string(luabind::object const& o) { using namespace luabind; if (type(o) == LUA_TSTRING) return object_cast<std::string>(o); lua_State* L = o.interpreter(); LUABIND_CHECK_STACK(L);#ifdef BOOST_NO_STRINGSTREAM std::strstream s;#else std::stringstream s;#endif if (type(o) == LUA_TNUMBER) { s << object_cast<float>(o); return s.str(); } s << "<" << lua_typename(L, type(o)) << ">";#ifdef BOOST_NO_STRINGSTREAM s << std::ends;#endif return s.str(); } std::string member_to_string(luabind::object const& e) {#if !defined(LUABIND_NO_ERROR_CHECKING) using namespace luabind; lua_State* L = e.interpreter(); LUABIND_CHECK_STACK(L); if (type(e) == LUA_TFUNCTION) { e.push(L); detail::stack_pop p(L, 1); { if (lua_getupvalue(L, -1, 3) == 0) return to_string(e); detail::stack_pop p2(L, 1); if (lua_touserdata(L, -1) != reinterpret_cast<void*>(0x1337)) return to_string(e); }#ifdef BOOST_NO_STRINGSTREAM std::strstream s;#else std::stringstream s;#endif { lua_getupvalue(L, -1, 2); detail::stack_pop p2(L, 1); int b = lua_toboolean(L, -1); s << "<c++ function"; if (b) s << " (default)"; s << "> "; } { lua_getupvalue(L, -1, 1); detail::stack_pop p2(L, 1); method_rep* m = static_cast<method_rep*>(lua_touserdata(L, -1)); s << m << "\n"; for (std::vector<overload_rep>::const_iterator i = m->overloads().begin(); i != m->overloads().end(); ++i) { std::string str; i->get_signature(L, str); s << " " << str << "\n"; } }#ifdef BOOST_NO_STRINGSTREAM s << std::ends;#endif return s.str(); } return to_string(e);#else return "";#endif }}std::string luabind::detail::class_rep::class_info_string(lua_State* L) const{#ifdef BOOST_NO_STRINGSTREAM std::strstream ret;#else std::stringstream ret;#endif ret << "CLASS: " << m_name << "\n"; ret << "dynamic dispatch functions:\n------------------\n"; for (luabind::iterator i(m_table), end; i != end; ++i) { luabind::object e = *i; ret << " " << to_string(i.key()) << ": " << member_to_string(e) << "\n"; } ret << "default implementations:\n------------------\n"; for (luabind::iterator i(m_default_table), end; i != end; ++i) { luabind::object e = *i; ret << " " << to_string(i.key()) << ": " << member_to_string(e) << "\n"; }#ifdef BOOST_NO_STRINGSTREAM ret << std::ends;#endif return ret.str();}#endifvoid luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::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 typedef std::list<detail::method_rep> methods_t; for (methods_t::const_iterator i = bcrep->m_methods.begin(); i != bcrep->m_methods.end(); ++i) { add_method(*i); } // 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) { callback& m = m_getters[i->first]; m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset; m.func = i->second.func;#ifndef LUABIND_NO_ERROR_CHECKING m.match = i->second.match; m.sig = i->second.sig;#endif } // 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) { callback& m = m_setters[i->first]; m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset; m.func = i->second.func;#ifndef LUABIND_NO_ERROR_CHECKING m.match = i->second.match; m.sig = i->second.sig;#endif } // 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) { int& v = m_static_constants[i->first]; 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);}int luabind::detail::class_rep::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; 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); } base->get_table(L); 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); // 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.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 += 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) { { std::string msg = "call of overloaded constructor '"; msg += base->m_name; msg += "("; msg += stack_content_by_name(L, 2); msg += ")' is ambiguous"; lua_pushstring(L, msg.c_str()); } 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 lua_pushvalue(L, lua_upvalueindex(2)); weak_ref backref(L, -1); lua_pop(L, 1); void* storage_ptr = obj->ptr(); if (!rep->overloads[match_index].has_wrapped_construct()) { // if the type doesn't have a wrapped type, use the ordinary constructor void* instance = rep->overloads[match_index].construct(L, backref); if (crep->has_holder()) { crep->m_construct_holder(storage_ptr, instance); } else { obj->set_object(instance); } } else { // get reference to lua object/* lua_pushvalue(L, lua_upvalueindex(2)); detail::lua_reference ref; ref.set(L); void* instance = rep->overloads[match_index].construct_wrapped(L, ref);*/ void* instance = rep->overloads[match_index].construct_wrapped(L, backref); if (crep->has_holder()) { crep->m_construct_holder(storage_ptr, instance); } else { obj->set_object(instance); } } // 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 error&) { } 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()); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?