📄 class_rep_scope.hpp
字号:
std::string msg = crep->name();
msg += "() threw an exception";
lua_pushstring(L, msg.c_str());
}
}
// we can only reach this line if an exception was thrown
lua_error(L);
return 0; // will never be reached
#endif
}
static int implicit_cast(const class_rep* from, const class_rep* to, int& pointer_offset)
{
int offset = 0;
if (LUABIND_TYPE_INFO_EQUAL(from->type(), to->type())) return 0;
for (std::vector<class_rep::base_info>::const_iterator i = from->bases().begin(); i != from->bases().end(); ++i)
{
int steps = implicit_cast(i->base, to, offset);
pointer_offset = offset + i->pointer_offset;
if (steps >= 0) return steps + 2;
}
return -1;
}
// the functions dispatcher assumes the following:
// there is one upvalue that points to the method_rep that this dispatcher is to call
// the first parameter on the lua stack is an object_rep that points to the object the
// call is being made on
static int function_dispatcher(lua_State* L)
{
method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
object_rep* obj = reinterpret_cast<object_rep*>(lua_touserdata(L, 1));
#ifndef LUABIND_NO_ERROR_CHECKING
if (is_class_object(L, 1) == 0)
{
{
std::string msg = "No self reference given as first parameter to member function '";
msg += rep->crep->name();
msg += ":";
msg += rep->name;
msg += "'. Have you used '.' instead of ':'?";
lua_pushstring(L, msg.c_str());
}
lua_error(L);
}
int p;
if (implicit_cast(obj->crep(), rep->crep, p) < 0)
{
{
std::string msg = "invalid self reference given to '";
msg += rep->crep->name();
msg += ":";
msg += rep->name;
msg += "'";
lua_pushstring(L, msg.c_str());
}
lua_error(L);
}
#endif
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().begin(), rep->overloads().end(), 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, 2);
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, 2);
msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";
std::vector<overload_rep> candidates;
find_exact_match(L, rep->overloads().begin(), rep->overloads().end(), min_match, num_params, candidates);
std::string function_name;
function_name += rep->crep->name();
function_name += ":";
function_name += rep->name;
msg += get_overload_signatures(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];
return o.call(L, *obj);
#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 = rep->crep->name();
msg += ":";
msg += rep->name;
msg += "() threw an exception";
lua_pushstring(L, msg.c_str());
}
// we can only reach this line if an exception was thrown
lua_error(L);
return 0; // will never be reached
#endif
}
struct base_info
{
int pointer_offset; // the offset added to the pointer to obtain a basepointer (due to multiple-inheritance)
class_rep* base;
};
inline void add_base_class(const 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
for (std::map<const char*, method_rep, ltstr>::const_iterator i = bcrep->m_methods.begin(); i != bcrep->m_methods.end(); ++i)
{
#ifndef LUABIND_DONT_COPY_STRINGS
m_strings.push_back(dup_string(i->first));
method_rep& m = m_methods[m_strings.back()];
#else
method_rep& m = m_methods[i->first];
#endif
m.name = i->first;
m.crep = this;
for (std::vector<overload_rep>::const_iterator j = i->second.overloads().begin(); j != i->second.overloads().end(); ++j)
{
overload_rep o = *j;
o.add_offset(binfo.pointer_offset);
m.add_overload(o);
}
}
// 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)
{
#ifndef LUABIND_DONT_COPY_STRINGS
m_strings.push_back(dup_string(i->first));
callback& m = m_getters[m_strings.back()];
#else
callback& m = m_getters[i->first];
#endif
m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
m.func = i->second.func;
}
// 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)
{
#ifndef LUABIND_DONT_COPY_STRINGS
// TODO: optimize this by not copying the string if it already exists in m_setters.
// This goes for m_getters, m_static_constants and m_functions too. Both here
// in add_base() and in the add_function(), add_getter() ... functions.
m_strings.push_back(dup_string(i->first));
callback& m = m_setters[m_strings.back()];
#else
callback& m = m_setters[i->first];
#endif
m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
m.func = i->second.func;
}
// 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)
{
#ifndef LUABIND_DONT_COPY_STRINGS
m_strings.push_back(dup_string(i->first));
int& v = m_static_constants[m_strings.back()];
#else
int& v = m_static_constants[i->first];
#endif
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);
}
inline const std::vector<base_info>& bases() const throw() { return m_bases; }
inline LUABIND_TYPE_INFO type() const throw() { return m_type; }
inline void set_type(LUABIND_TYPE_INFO t) { m_type = t; }
inline void add_function(const char* name, const overload_rep& o)
{
#ifdef LUABIND_DONT_COPY_STRINGS
detail::method_rep& method = m_methods[name];
method.name = name;
#else
m_strings.push_back(dup_string(name));
detail::method_rep& method = m_methods[m_strings.back()];
method.name = m_strings.back();
#endif
method.add_overload(o);
method.crep = this;
}
inline void add_constructor(const detail::construct_rep::overload_t& o)
{
m_constructor.overloads.push_back(o);
}
inline void add_wrapped_constructor(const detail::construct_rep::overload_t& o)
{
m_wrapped_constructor.overloads.push_back(o);
}
inline const char* name() const throw()
{
#ifdef LUABIND_DONT_COPY_STRINGS
return m_name;
#else
return m_name.c_str();
#endif
}
inline void add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
{
callback c;
c.func = g;
c.pointer_offset = 0;
#ifndef LUABIND_DONT_COPY_STRINGS
m_strings.push_back(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)
{
callback c;
c.func = s;
c.pointer_offset = 0;
#ifndef LUABIND_DONT_COPY_STRINGS
m_strings.push_back(dup_string(name));
m_setters[m_strings.back()] = c;
#else
m_setters[name] = c;
#endif
}
#ifndef LUABIND_NO_ERROR_CHECKING
inline void add_operator(lua_State*, int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), void(*sig)(lua_State*, std::string&), int arity)
#else
inline void add_operator(lua_State*, int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
#endif
{
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);
}
// the lua reference to this class_rep
inline int self_ref() const throw() { return m_self_ref; }
// the lua reference to the metatable for this class' instances
inline int metatable_ref() const throw() { return m_instance_metatable; }
inline int table_ref() const { return m_table_ref; }
inline void(*destructor() const)(void*) { return m_destructor; }
inline class_type get_class_type() const { return m_class_type; }
void add_static_constant(const char* name, int val)
{
#ifndef LUABIND_DONT_COPY_STRINGS
m_strings.push_back(dup_string(name));
m_static_constants[m_strings.back()] = val;
#else
m_static_constants[name] = val;
#endif
}
static inline int 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;
// std::cout << "__super of " << base->name() << "\n";
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);
}
// std::cout << " lua_class\n";
detail::getref(L, base->table_ref());
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);
// std::cout << " cpp_class\n";
// 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.begin(), rep->overloads.end(), 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)
{
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -