Changed calling conventions again
This commit is contained in:
@@ -11,28 +11,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
#include <string>
|
||||
|
||||
// LuaArgCheck
|
||||
//
|
||||
// This is a template that, when given a lua_CFunction that doesn't
|
||||
// verify the number of arguments on the stack, returns a new lua_CFunction
|
||||
// that *does* verify the number of arguments on the stack.
|
||||
//
|
||||
// In general, your lua_CFunctions should not verify the number of
|
||||
// arguments on the stack. Instead, they should assume that the stack
|
||||
// contains arbitrary stuff underneath the arguments. That makes your
|
||||
// lua_CFunctions callable from both C and Lua. But it is desirable to
|
||||
// check arguments (only when calling from lua), so it is useful to use
|
||||
// LuaArgCheck when turning a lua_CFunction into a lua closure.
|
||||
//
|
||||
template<int N, lua_CFunction FN>
|
||||
int LuaArgCheck(lua_State *L) {
|
||||
if (lua_gettop(L) != N) {
|
||||
lua_pushfstring(L, "expected %d arguments, got %d", N, lua_gettop(L));
|
||||
lua_error(L);
|
||||
}
|
||||
FN(L);
|
||||
}
|
||||
#include <vector>
|
||||
|
||||
// LuaSlot
|
||||
//
|
||||
@@ -53,10 +32,6 @@ private:
|
||||
return index_;
|
||||
}
|
||||
public:
|
||||
LuaSlot(int n) {
|
||||
index_ = n;
|
||||
}
|
||||
|
||||
LuaSlot() {
|
||||
index_ = 0;
|
||||
}
|
||||
@@ -72,8 +47,15 @@ class LuaArg : public LuaSlot {};
|
||||
class LuaRet : public LuaSlot {};
|
||||
class LuaVar : public LuaSlot {};
|
||||
|
||||
extern LuaSlot LuaRegistry;
|
||||
extern LuaSlot LuaGlobals;
|
||||
class LuaSpecial : public LuaSlot {
|
||||
public:
|
||||
LuaSpecial(int n) {
|
||||
index_ = n;
|
||||
}
|
||||
};
|
||||
|
||||
extern LuaSpecial LuaRegistry;
|
||||
extern LuaSpecial LuaGlobals;
|
||||
|
||||
class LuaUpvalue : public LuaSlot {
|
||||
public:
|
||||
@@ -82,6 +64,9 @@ class LuaUpvalue : public LuaSlot {
|
||||
}
|
||||
};
|
||||
|
||||
class LuaNilMarker {};
|
||||
extern LuaNilMarker LuaNil;
|
||||
|
||||
class LuaStack {
|
||||
private:
|
||||
int narg_;
|
||||
@@ -150,6 +135,9 @@ public:
|
||||
LuaStack(lua_State *L, SS & ... stackslots) {
|
||||
L_ = L;
|
||||
count_slots<0, 0, 0>(stackslots...);
|
||||
if (lua_gettop(L) < narg_) {
|
||||
luaL_error(L, "not enough arguments on stack");
|
||||
}
|
||||
assign_slots(argpos_, varpos_, retpos_, stackslots...);
|
||||
clear_frame();
|
||||
}
|
||||
@@ -158,15 +146,62 @@ public:
|
||||
|
||||
int result();
|
||||
|
||||
public:
|
||||
static void reg(lua_State *L, const char *classname, const char *funcname, lua_CFunction fn);
|
||||
private:
|
||||
// Push any value on the stack, by type.
|
||||
void push_any_value(LuaNilMarker s) const { lua_pushnil(L_); }
|
||||
void push_any_value(LuaSlot s) const { lua_pushvalue(L_, s); }
|
||||
void push_any_value(const std::string &s) const { lua_pushlstring(L_, s.c_str(), s.size()); }
|
||||
void push_any_value(const char *s) const { lua_pushstring(L_, s); }
|
||||
void push_any_value(double s) const { lua_pushnumber(L_, s); }
|
||||
void push_any_value(int s) const { lua_pushnumber(L_, s); }
|
||||
void push_any_value(bool b) const { lua_pushboolean(L_, b ? 1:0); }
|
||||
|
||||
void setnil(LuaSlot target) const;
|
||||
void setboolean(LuaSlot target, bool b) const;
|
||||
void setboolean(LuaSlot target, int b) const;
|
||||
void setstring(LuaSlot target, const char *str) const;
|
||||
void setstring(LuaSlot target, const std::string &str) const;
|
||||
void setnumber(LuaSlot target, double value) const;
|
||||
// Push multiple values on the stack, in order, by type.
|
||||
template<typename T0, typename... T>
|
||||
void push_any_values(T0 arg0, T... args) {
|
||||
push_any_value(arg0);
|
||||
push_any_values(args...);
|
||||
}
|
||||
void push_any_values() {
|
||||
}
|
||||
|
||||
private:
|
||||
// Push everything after the CFunction. Used in the implementation
|
||||
// of the 'call' template function.
|
||||
template<typename... T>
|
||||
void push_after_cfunction(LuaSlot s, T... args) {
|
||||
push_after_cfunction(args...);
|
||||
}
|
||||
template<typename... T>
|
||||
void push_after_cfunction(lua_CFunction f, T... args) {
|
||||
push_any_values(args...);
|
||||
}
|
||||
|
||||
// Call the CFunction, verify that the number of return values is
|
||||
// correct, and pop everything before the CFunction. Used in the
|
||||
// implementation of the 'call' template function.
|
||||
template<int NRET, typename... T>
|
||||
void call_cfunction_and_pop(int otop, LuaSlot s, T... args) {
|
||||
call_cfunction_and_pop<NRET+1>(otop, args...);
|
||||
lua_replace(L_, s);
|
||||
}
|
||||
template<int NRET, typename... T>
|
||||
void call_cfunction_and_pop(int otop, lua_CFunction fn, T... args) {
|
||||
int nret = fn(L_);
|
||||
check_nret(NRET, otop, nret);
|
||||
}
|
||||
|
||||
// Check number of return values: xpected number of return values,
|
||||
// original stack top, and number of declared return values.
|
||||
void check_nret(int xnret, int otop, int nret) const;
|
||||
public:
|
||||
template<typename T>
|
||||
void set(LuaSlot target, T value) const {
|
||||
push_any_value(value);
|
||||
lua_replace(L_, target);
|
||||
}
|
||||
|
||||
int type(LuaSlot s) const { return lua_type(L_, s); }
|
||||
|
||||
bool isboolean(LuaSlot s) const { return lua_isboolean(L_, s); }
|
||||
bool iscfunction(LuaSlot s) const { return lua_iscfunction(L_, s); }
|
||||
@@ -199,40 +234,72 @@ public:
|
||||
|
||||
int next(LuaSlot tab, LuaSlot key, LuaSlot value) const;
|
||||
|
||||
void rawget(LuaSlot target, LuaSlot tab, LuaSlot key) const {
|
||||
lua_pushvalue(L_, key);
|
||||
template<typename KT>
|
||||
void rawget(LuaSlot target, LuaSlot tab, KT key) const {
|
||||
push_any_value(key);
|
||||
lua_rawget(L_, tab);
|
||||
lua_replace(L_, target);
|
||||
}
|
||||
|
||||
void rawset(LuaSlot tab, LuaSlot key, LuaSlot value) const {
|
||||
lua_pushvalue(L_, key);
|
||||
lua_pushvalue(L_, value);
|
||||
template<typename KT, typename VT>
|
||||
void rawset(LuaSlot tab, KT key, VT value) const {
|
||||
push_any_value(key);
|
||||
push_any_value(value);
|
||||
lua_rawset(L_, tab);
|
||||
}
|
||||
|
||||
void setfield(LuaSlot tab, const char *field, LuaSlot value) const {
|
||||
lua_pushvalue(L_, value);
|
||||
template<typename VT>
|
||||
void setfield(LuaSlot tab, const char *field, VT value) const {
|
||||
push_any_value(value);
|
||||
lua_setfield(L_, tab, field);
|
||||
}
|
||||
|
||||
void setfield(LuaSlot tab, const char *field, const char *value) const {
|
||||
lua_pushstring(L_, value);
|
||||
lua_setfield(L_, tab, field);
|
||||
}
|
||||
|
||||
void setfield(LuaSlot tab, const char *field, const std::string &value) const {
|
||||
lua_pushlstring(L_, value.c_str(), value.size());
|
||||
lua_setfield(L_, tab, field);
|
||||
}
|
||||
|
||||
void getfield(LuaSlot target, LuaSlot tab, const char *field) const {
|
||||
lua_getfield(L_, tab, field);
|
||||
lua_replace(L_, target);
|
||||
}
|
||||
|
||||
|
||||
// Call invokes any C function. It pushes the arguments on the stack,
|
||||
// calls the cfunction, verifies that the number of return values is as
|
||||
// expected, and pops the return values into LuaVars.
|
||||
template<typename... T>
|
||||
void call(T... args) {
|
||||
int otop = lua_gettop(L_);
|
||||
push_after_cfunction(args...);
|
||||
call_cfunction_and_pop<0>(otop, args...);
|
||||
}
|
||||
};
|
||||
|
||||
class LuaFunctionReg {
|
||||
private:
|
||||
int mode_;
|
||||
const char *name_;
|
||||
lua_CFunction func_;
|
||||
LuaFunctionReg *next_;
|
||||
|
||||
static LuaFunctionReg *LuaFunctionRegistry;
|
||||
|
||||
public:
|
||||
using List = std::vector<const LuaFunctionReg *>;
|
||||
|
||||
LuaFunctionReg(int m, const char *n, lua_CFunction f);
|
||||
static List all();
|
||||
|
||||
int get_mode() const { return mode_; }
|
||||
const char *get_name() const { return name_; }
|
||||
lua_CFunction get_func() const { return func_; }
|
||||
};
|
||||
|
||||
#define LuaDefineHidden(name) LuaDefineCore(name, 0)
|
||||
#define LuaDefineGlobalFunction(name) LuaDefineCore(name, 1)
|
||||
#define LuaDefineGlobalMethod(name) LuaDefineCore(name, 2)
|
||||
#define LuaDefineClassMethod(name) LuaDefineCore(name, 3)
|
||||
|
||||
#define LuaDefineCore(name, mode) \
|
||||
int name(lua_State *L); \
|
||||
LuaFunctionReg reg_##name(mode, #name, name); \
|
||||
int name(lua_State *L)
|
||||
|
||||
|
||||
|
||||
#endif // LUASTACK_HPP
|
||||
|
||||
Reference in New Issue
Block a user