📄 class_rep_scope.hpp
字号:
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
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;
}
static int 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);
return 0;
}
static int 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
static int 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
detail::getref(L, obj->lua_table_ref());
lua_pushvalue(L, 2);
lua_gettable(L, -2);
if (!lua_isnil(L, -1)) 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)) return 1;
lua_pop(L, 2);
if (lua_isnil(L, 2))
{
lua_pushnil(L);
return 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);
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
static int 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;
}
static int 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;
}
private:
// this is a pointer to the type_info structure for
// this type
// warning: this may be a problem when using dll:s, since
// typeid() may actually return different pointers for the same
// type.
LUABIND_TYPE_INFO m_type;
LUABIND_TYPE_INFO m_held_type;
typedef void*(*extract_ptr_t)(void*);
extract_ptr_t m_extract_underlying_fun;
// a list of info for every class this class derives from
// the information stored here is sufficient to do
// type casts to the base classes
std::vector<base_info> m_bases;
// the class' name (as given when registered to lua with class_)
#ifdef LUABIND_DONT_COPY_STRINGS
const char* m_name;
#else
std::string m_name;
#endif
// contains signatures for all constructors
construct_rep m_constructor;
construct_rep m_wrapped_constructor;
// a reference to this structure itself. Since this struct
// is kept inside lua (to let lua collect it when lua_close()
// is called) we need to lock it to prevent collection.
// the actual reference is not currently used.
int m_self_ref;
// a reference to the lua table that represents this class
// (only used if it is a lua class)
int m_table_ref;
// the type of this class.. determines if it's written in c++ or lua
class_type m_class_type;
// this is a lua reference that points to the lua table
// that is to be used as meta table for all instances
// of this class.
int m_instance_metatable;
// ***** the maps below contains all members in this class *****
// maps method names to a structure with more
// information about that method.
// that struct contains the function-signatures
// for every overload
std::map<const char*, method_rep, ltstr> m_methods;
#ifndef LUABIND_DONT_COPY_STRINGS
// this is where the strings that the maps contains
// pointer to are kept. To make sure they are destructed.
std::vector<char*> m_strings;
#endif
struct callback
{
boost::function2<int, lua_State*, int> func;
int pointer_offset;
};
// datamembers, some members may be readonly, and
// only have a getter function
std::map<const char*, callback, ltstr> m_getters;
std::map<const char*, callback, ltstr> m_setters;
struct operator_callback: public overload_rep_base
{
inline void set_fun(int (*f)(lua_State*)) { func = f; }
inline int call(lua_State* L) { return func(L); }
inline void set_arity(int arity) { m_arity = arity; }
private:
int(*func)(lua_State*);
};
std::vector<operator_callback> m_operators[number_of_operators]; // the operators in lua
void(*m_destructor)(void*);
std::map<const char*, int, ltstr> m_static_constants;
};
inline bool 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;
}
}}
#endif // LUABIND_CLASS_REP_HPP_INCLUDED
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -