class_rep.cpp.svn-base
来自「本人找过多个在linux下c++的lua5.1封装库,但很少.luabind已经」· SVN-BASE 代码 · 共 1,676 行 · 第 1/3 页
SVN-BASE
1,676 行
// 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)); // get first table crep->get_table(L); // copy key, value lua_pushvalue(L, -3); lua_pushvalue(L, -3); lua_rawset(L, -3); // pop table lua_pop(L, 1); // get default table crep->get_default_table(L); 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); detail::lua_reference ref; ref.set(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)); void* obj_ptr; void* held_storage; boost::tie(obj_ptr, held_storage) = crep->allocate(L); (new(obj_ptr) object_rep(crep, flags, ref))->set_object(held_storage); 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); crep->get_table(L); 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 pointerint 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) // BUG: This might catch members called "__ok\0foobar" const char* key = lua_tostring(L, 2); 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(); assert(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 crep->get_table(L); 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*, 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 pointerint 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) // BUG: This will not work with keys with extra nulls in them const char* key = lua_tostring(L, 2); std::map<const char*, class_rep::callback, ltstr>::iterator j = crep->m_setters.find(key); // if the strlen(key) is not the true length, // it means that the member-name contains // extra nulls. luabind does not support such // names as member names. So, use the lua // table as fall-back if (j == crep->m_setters.end() || std::strlen(key) != lua_strlen(L, 2)) { 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::lua_reference const& tbl = obj->get_lua_table(); assert(tbl.is_valid()); tbl.get(L); 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;}/* stack: 1: class_rep 2: member name*/int luabind::detail::class_rep::static_class_gettable(lua_State* L){ class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1)); // look in the static function table crep->get_default_table(L); 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); if (std::strlen(key) != lua_strlen(L, 2)) { lua_pushnil(L); return 1; } 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; }#ifndef LUABIND_NO_ERROR_CHECKING { std::string msg = "no static '"; msg += key; msg += "' in class '"; msg += crep->name(); msg += "'"; lua_pushstring(L, msg.c_str()); } lua_error(L);#endif lua_pushnil(L); return 1;}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;// lua_pushvalue(L, -1); // copy the object ref crep->get_table(L); lua_pushstring(L, "__finalize"); lua_gettable(L, -2); lua_remove(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 assert(obj == 0 || obj->crep() == this); int steps = 0; int offset = 0; if (!(LUABIND_TYPE_INFO_EQUAL(holder_type(), target_type)) && !(LUABIND_TYPE_INFO_EQUAL(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 (obj == 0) { // we are trying to convert nil to a holder type m_default_construct_holder(target_memory); return target_memory; } // 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 == 0) { // we are trying to convert nil to a const holder type m_default_construct_const_holder(target_memory); return target_memory; } 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()) { assert(obj); // this means that we have a holder type where the // raw-pointer needs to be extracted raw_pointer = extractor()(obj->ptr()); } else { if (obj == 0) raw_pointer = 0; else raw_pointer = obj->ptr(); } return static_cast<char*>(raw_pointer) + offset;}void luabind::detail::class_rep::cache_operators(lua_State* L){ m_operator_cache = 0x1; for (int i = 0; i < number_of_operators; ++i) { get_table(L); 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 luabind::detail::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) != 0;}// this will merge all overloads of fun into the list of// overloads in this classvoid luabind::detail::class_rep::add_method(luabind::detail::method_rep const& fun){ typedef std::list<detail::method_rep> methods_t; methods_t::iterator m = std::find_if( m_methods.begin() , m_methods.end() , method_name(fun.name)); if (m == m_methods.end()) { m_methods.push_back(method_rep()); m = m_methods.end(); std::advance(m, -1); m->name = fun.name; } m->crep = this; typedef std::vector<detail::overload_rep> overloads_t; for (overloads_t::const_iterator j = fun.overloads().begin(); j != fun.overloads().end(); ++j) { detail::overload_rep o = *j; m->add_overload(o); }}// this function will add all the overloads in method rep to// this class' lua tables. If there already are overloads with this// name, thses will simply be appended to the overload listvoid luabind::detail::class_rep::register_methods(lua_State* L){ LUABIND_CHECK_STACK(L); // insert the function in the normal member table // and in the default member table m_default_table.push(L); m_table.push(L); // pops the tables detail::stack_pop pop_tables(L, 2); for (std::list<method_rep>::const_iterator m = m_methods.begin(); m != m_methods.end(); ++m) { // create the function closure in m_table lua_pushstring(L, m->name); lua_pushlightuserdata(L, const_cast<void*>((const void*)&(*m))); lua_pushboolean(L, 0); lua_pushlightuserdata(L, reinterpret_cast<void*>(0x1337)); lua_pushcclosure(L, function_dispatcher, 3); lua_settable(L, -3); // create the function closure in m_default_table lua_pushstring(L, m->name); lua_pushlightuserdata(L, const_cast<void*>((const void*)&(*m))); lua_pushboolean(L, 1); lua_pushlightuserdata(L, reinterpret_cast<void*>(0x1337)); lua_pushcclosure(L, function_dispatcher, 3); lua_settable(L, -4); }}const class_rep::property_map& luabind::detail::class_rep::properties() const{ return m_getters;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?