📄 class.hpp
字号:
// the following two functions are the ones that returns
// a pointer to a const_held_type_constructor, or 0 if there
// is no held_type
template<class HolderType>
struct const_holder_constructor
{
typedef void(*constructor)(void*,void*);
template<class T>
static constructor apply(detail::type<T>)
{
return get_const_holder_constructor(detail::type<T>(), luabind::get_const_holder(static_cast<HolderType*>(0)));
}
private:
template<class T, class ConstHolderType>
static constructor get_const_holder_constructor(detail::type<T>, ConstHolderType*)
{
return &internal_construct_holder<ConstHolderType, T>::apply;
}
};
template<>
struct const_holder_constructor<detail::null_type>
{
typedef void(*constructor)(void*,void*);
template<class T>
static constructor apply(detail::type<T>)
{
return 0;
}
};
// this is a selector that returns the size of the held_type
// or 0 if we don't have a held_type
template <class HolderType>
struct internal_holder_size
{
static int apply() { return get_internal_holder_size(luabind::get_const_holder(static_cast<HolderType*>(0))); }
private:
template<class ConstHolderType>
static int get_internal_holder_size(ConstHolderType*)
{
return max<sizeof(HolderType), sizeof(ConstHolderType)>::value;
}
};
template <>
struct internal_holder_size<detail::null_type>
{
static int apply() { return 0; }
};
// if we have a held type, return the destructor to it
// note the difference. The held_type should only be destructed (not deleted)
// since it's constructed in the lua userdata
template<class HeldType>
struct internal_holder_destructor
{
typedef void(*destructor_t)(void*);
template<class T>
static destructor_t apply(detail::type<T>)
{
return &detail::destruct_only_s<HeldType>::apply;
}
};
// if we don't have a held type, return the destructor of the raw type
template<>
struct internal_holder_destructor<detail::null_type>
{
typedef void(*destructor_t)(void*);
template<class T>
static destructor_t apply(detail::type<T>)
{
return &detail::delete_s<T>::apply;
}
};
// if we have a held type, return the destructor to it's const version
template<class HolderType>
struct internal_const_holder_destructor
{
typedef void(*destructor_t)(void*);
template<class T>
static destructor_t apply(detail::type<T>)
{
return const_holder_type_destructor(luabind::get_const_holder(static_cast<HolderType*>(0)));
}
private:
template<class ConstHolderType>
static destructor_t const_holder_type_destructor(ConstHolderType*)
{
return &detail::destruct_only_s<ConstHolderType>::apply;
}
};
// if we don't have a held type, return the destructor of the raw type
template<>
struct internal_const_holder_destructor<detail::null_type>
{
typedef void(*destructor_t)(void*);
template<class T>
static destructor_t apply(detail::type<T>)
{
return 0;
}
};
template<class HolderType>
struct get_holder_alignment
{
static int apply()
{
return internal_alignment(luabind::get_const_holder(static_cast<HolderType*>(0)));
}
private:
template<class ConstHolderType>
static int internal_alignment(ConstHolderType*)
{
return detail::max<boost::alignment_of<HolderType>::value
, boost::alignment_of<ConstHolderType>::value>::value;
}
};
template<>
struct get_holder_alignment<detail::null_type>
{
static int apply()
{
return 1;
}
};
} // detail
struct class_base: detail::scoped_object
{
protected:
struct base_desc
{
LUABIND_TYPE_INFO type;
int ptr_offset;
};
private:
#ifndef NDEBUG
bool m_cloned;
#endif
const char* m_name;
std::map<const char*, detail::method_rep, detail::ltstr> m_methods;
// datamembers, some members may be readonly, and
// only have a getter function
std::map<const char*, detail::class_rep::callback, detail::ltstr> m_getters;
std::map<const char*, detail::class_rep::callback, detail::ltstr> m_setters;
// the operators in lua
std::vector<detail::class_rep::operator_callback> m_operators[detail::number_of_operators];
std::map<const char*, int, detail::ltstr> m_static_constants;
std::vector<base_desc> m_bases;
detail::construct_rep m_constructor;
void(*m_destructor)(void*);
void(*m_const_holder_destructor)(void*);
void*(*m_extractor)(void*);
const void*(*m_const_extractor)(void*);
void(*m_const_converter)(void*,void*);
void(*m_construct_holder)(void*, void*);
void(*m_construct_const_holder)(void*, void*);
int m_holder_size;
int m_holder_alignment;
LUABIND_TYPE_INFO m_type;
LUABIND_TYPE_INFO m_holder_type;
LUABIND_TYPE_INFO m_const_holder_type;
#ifndef LUABIND_DONT_COPY_STRINGS
// the maps that contains char pointers points into
// this vector of strings.
std::vector<char*> m_strings;
#endif
public:
// public 'cause of enum_maker, FIX
void add_static_constant(const char* name, int val)
{
m_static_constants[name] = val;
}
protected:
void init(LUABIND_TYPE_INFO type
, LUABIND_TYPE_INFO holder_type
, void*(*extractor)(void*)
, const void*(*const_extractor)(void*)
, void(*const_converter)(void*,void*)
, void(*holder_constructor)(void*,void*)
, void(*const_holder_constructor)(void*,void*)
, void(*destructor)(void*)
, void(*const_holder_destructor)(void*)
, int holder_size
, int holder_alignment)
{
m_type = type;
m_holder_type = holder_type;
m_extractor = extractor;
m_const_extractor = const_extractor;
m_const_converter = const_converter;
m_construct_holder = holder_constructor;
m_construct_const_holder = const_holder_constructor;
m_destructor = destructor;
m_const_holder_destructor = const_holder_destructor;
m_holder_size = holder_size;
m_holder_alignment = holder_alignment;
}
template<class T>
void set_const_holder_type(T*)
{
m_const_holder_type = LUABIND_TYPEID(T);
}
inline void add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
{
detail::class_rep::callback c;
c.func = g;
c.pointer_offset = 0;
#ifndef LUABIND_DONT_COPY_STRINGS
m_strings.push_back(detail::dup_string(name));
m_getters[m_strings.back()] = c;
#else
m_getters[name] = c;
#endif
}
inline void add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
{
detail::class_rep::callback c;
c.func = s;
c.pointer_offset = 0;
#ifndef LUABIND_DONT_COPY_STRINGS
m_strings.push_back(detail::dup_string(name));
m_setters[m_strings.back()] = c;
#else
m_setters[name] = c;
#endif
}
void add_base(const base_desc& b)
{
m_bases.push_back(b);
}
public:
void add_constructor(const detail::construct_rep::overload_t& o)
{
m_constructor.overloads.push_back(o);
}
void add_method(const char* name, const detail::overload_rep& o)
{
#ifdef LUABIND_DONT_COPY_STRINGS
detail::method_rep& method = m_methods[name];
method.name = name;
#else
m_strings.push_back(detail::dup_string(name));
detail::method_rep& method = m_methods[m_strings.back()];
method.name = m_strings.back();
#endif
method.add_overload(o);
method.crep = 0;
}
#ifndef LUABIND_NO_ERROR_CHECKING
inline void add_operator(int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), void(*sig)(lua_State*, std::string&), int arity)
#else
inline void add_operator(int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
#endif
{
detail::class_rep::operator_callback o;
o.set_fun(func);
o.set_match_fun(matcher);
o.set_arity(arity);
#ifndef LUABIND_NO_ERROR_CHECKING
o.set_sig_fun(sig);
#endif
m_operators[op_id].push_back(o);
}
const char* name() const { return m_name; }
class_base(const char* name)
{
#ifndef LUABIND_DONT_COPY_STRINGS
m_strings.push_back(detail::dup_string(name));
m_name = m_strings.back();
#else
m_name = name;
#endif
#ifndef NDEBUG
m_cloned = false;
#endif
}
virtual ~class_base()
{
// if we are copying strings, we have to destroy them too
#ifndef LUABIND_DONT_COPY_STRINGS
for (std::vector<char*>::iterator i = m_strings.begin(); i != m_strings.end(); ++i)
delete[] *i;
#endif
}
// pushes the class_rep on the lua stack
virtual void commit(lua_State* L)
{
assert(!m_cloned && "class already commited");
detail::getref(L, scope_stack::top(L));
lua_pushstring(L, m_name);
detail::class_rep* crep;
detail::class_registry* r = detail::class_registry::get_registry(L);
// create a class_rep structure for this class.
// allocate it within lua to let lua collect it on
// lua_close(). This is better than allocating it
// as a static, since it will then be destructed
// when the program exits instead.
// warning: we assume that lua will not
// move the userdata memory.
lua_newuserdata(L, sizeof(detail::class_rep));
crep = reinterpret_cast<detail::class_rep*>(lua_touserdata(L, -1));
new(crep) detail::class_rep( m_type
, m_name
, L
, m_destructor
, m_const_holder_destructor
, m_holder_type
, m_const_holder_type
, m_extractor
, m_const_extractor
, m_const_converter
, m_construct_holder
, m_construct_const_holder
, m_holder_size
, m_holder_alignment);
// register this new type in the class registry
r->add_class(m_type, crep);
if (!(LUABIND_TYPE_INFO_EQUAL(m_holder_type, LUABIND_INVALID_TYPE_INFO)))
{
// if we have a held type
// we have to register it in the class-table
// but only for the base class, if it already
// exists, we don't have to register it
detail::class_rep* c = r->find_class(m_holder_type);
if (c == 0)
{
r->add_class(m_holder_type, crep);
r->add_class(m_const_holder_type, crep);
}
}
// add methods
for (std::map<const char*, detail::method_rep, detail::ltstr>::iterator i = m_methods.begin();
i != m_methods.end();
++i)
{
i->second.crep = crep;
}
std::swap(crep->m_methods, m_methods);
// constructors
m_constructor.swap(crep->m_constructor);
#ifndef LUABIND_DONT_COPY_STRINGS
assert(crep->m_strings.empty() && "Internal error");
std::swap(crep->m_strings, m_strings);
#endif
std::swap(crep->m_getters, m_getters);
std::swap(crep->m_setters, m_setters);
for(int i = 0; i < detail::number_of_operators; ++i)
std::swap(crep->m_operators[i], m_operators[i]);
std::swap(crep->m_static_constants, m_static_constants);
for (std::vector<base_desc>::iterator i = m_bases.begin();
i != m_bases.end();
++i)
{
detail::class_registry* r = detail::class_registry::get_registry(L);
// the baseclass' class_rep structure
detail::class_rep* bcrep = r->find_class(i->type);
detail::class_rep::base_info base;
base.pointer_offset = i->ptr_offset;
base.base = bcrep;
crep->add_base_class(base);
}
lua_settable(L, -3);
lua_pop(L, 1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -