mirror of
https://github.com/love2d/love-android.git
synced 2026-08-19 12:14:49 +02:00
Using latest love-android branch (9a508a54700d)
This commit is contained in:
@@ -26,13 +26,13 @@ namespace love
|
||||
const char REFERENCE_TABLE_NAME[] = "love-references";
|
||||
|
||||
Reference::Reference()
|
||||
: L(nullptr)
|
||||
: pinnedL(nullptr)
|
||||
, idx(LUA_REFNIL)
|
||||
{
|
||||
}
|
||||
|
||||
Reference::Reference(lua_State *L)
|
||||
: L(L)
|
||||
: pinnedL(nullptr)
|
||||
, idx(LUA_REFNIL)
|
||||
{
|
||||
ref(L);
|
||||
@@ -46,7 +46,7 @@ Reference::~Reference()
|
||||
void Reference::ref(lua_State *L)
|
||||
{
|
||||
unref(); // Just to be safe.
|
||||
this->L = L;
|
||||
pinnedL = luax_getpinnedthread(L);
|
||||
luax_insist(L, LUA_REGISTRYINDEX, REFERENCE_TABLE_NAME);
|
||||
lua_insert(L, -2); // Move reference table behind value.
|
||||
idx = luaL_ref(L, -2);
|
||||
@@ -57,38 +57,26 @@ void Reference::unref()
|
||||
{
|
||||
if (idx != LUA_REFNIL)
|
||||
{
|
||||
luax_insist(L, LUA_REGISTRYINDEX, REFERENCE_TABLE_NAME);
|
||||
luaL_unref(L, -1, idx);
|
||||
lua_pop(L, 1);
|
||||
// We use a pinned thread/coroutine for the Lua state because we know it
|
||||
// hasn't been garbage collected and is valid, as long as the whole lua
|
||||
// state is still open.
|
||||
luax_insist(pinnedL, LUA_REGISTRYINDEX, REFERENCE_TABLE_NAME);
|
||||
luaL_unref(pinnedL, -1, idx);
|
||||
lua_pop(pinnedL, 1);
|
||||
idx = LUA_REFNIL;
|
||||
}
|
||||
}
|
||||
|
||||
void Reference::push(lua_State *newL)
|
||||
void Reference::push(lua_State *L)
|
||||
{
|
||||
if (idx != LUA_REFNIL)
|
||||
{
|
||||
luax_insist(newL, LUA_REGISTRYINDEX, REFERENCE_TABLE_NAME);
|
||||
lua_rawgeti(newL, -1, idx);
|
||||
lua_remove(newL, -2);
|
||||
luax_insist(L, LUA_REGISTRYINDEX, REFERENCE_TABLE_NAME);
|
||||
lua_rawgeti(L, -1, idx);
|
||||
lua_remove(L, -2);
|
||||
}
|
||||
else
|
||||
lua_pushnil(newL);
|
||||
}
|
||||
|
||||
void Reference::push()
|
||||
{
|
||||
push(L);
|
||||
}
|
||||
|
||||
lua_State *Reference::getL() const
|
||||
{
|
||||
return L;
|
||||
}
|
||||
|
||||
void Reference::setL(lua_State *newL)
|
||||
{
|
||||
L = newL;
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
} // love
|
||||
|
||||
@@ -64,36 +64,17 @@ public:
|
||||
void unref();
|
||||
|
||||
/**
|
||||
* Pushes the referred value onto the stack of a different coroutine
|
||||
* in the same main Lua state.
|
||||
* THIS SHOULD NOT BE USED FOR DIFFERENT LUA STATES (created with
|
||||
* luaL_newstate)! Only with different coroutines!
|
||||
* Pushes the referred value onto the stack of the specified Lua coroutine.
|
||||
* NOTE: The coroutine *must* belong to the same Lua state that was used for
|
||||
* Reference::ref.
|
||||
**/
|
||||
void push(lua_State *newL);
|
||||
|
||||
/**
|
||||
* Pushes the referred value onto the stack.
|
||||
**/
|
||||
void push();
|
||||
|
||||
/**
|
||||
* Gets the Lua state associated with this
|
||||
* reference.
|
||||
**/
|
||||
lua_State *getL() const;
|
||||
|
||||
/**
|
||||
* Associates a new Lua state with this reference.
|
||||
* THIS IS DANGEROUS! It is only designed to be
|
||||
* used with different coroutines from the same
|
||||
* main Lua state!
|
||||
**/
|
||||
void setL(lua_State *newL);
|
||||
void push(lua_State *L);
|
||||
|
||||
private:
|
||||
|
||||
// The Lua state in which the reference resides.
|
||||
lua_State *L;
|
||||
// A pinned coroutine (probably the main thread) belonging to the Lua state
|
||||
// in which the reference resides.
|
||||
lua_State *pinnedL;
|
||||
|
||||
// Index to the Lua reference.
|
||||
int idx;
|
||||
|
||||
@@ -31,7 +31,7 @@ static love::Type extractudatatype(lua_State *L, int idx)
|
||||
Type t = INVALID_ID;
|
||||
if (!lua_isuserdata(L, idx))
|
||||
return t;
|
||||
if (luaL_getmetafield(L, idx, "__tostring") == 0)
|
||||
if (luaL_getmetafield(L, idx, "type") == 0)
|
||||
return t;
|
||||
lua_pushvalue(L, idx);
|
||||
int result = lua_pcall(L, 1, 1, 0);
|
||||
|
||||
@@ -47,6 +47,14 @@ static int w__gc(lua_State *L)
|
||||
}
|
||||
|
||||
static int w__tostring(lua_State *L)
|
||||
{
|
||||
Proxy *p = (Proxy *) lua_touserdata(L, 1);
|
||||
const char *typname = lua_tostring(L, lua_upvalueindex(1));
|
||||
lua_pushfstring(L, "%s: %p", typname, p->object);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int w__type(lua_State *L)
|
||||
{
|
||||
lua_pushvalue(L, lua_upvalueindex(1));
|
||||
return 1;
|
||||
@@ -83,7 +91,7 @@ Reference *luax_refif(lua_State *L, int type)
|
||||
|
||||
void luax_printstack(lua_State *L)
|
||||
{
|
||||
for (int i = 1; i<=lua_gettop(L); i++)
|
||||
for (int i = 1; i <= lua_gettop(L); i++)
|
||||
std::cout << i << " - " << luaL_typename(L, i) << std::endl;
|
||||
}
|
||||
|
||||
@@ -313,9 +321,9 @@ int luax_register_type(lua_State *L, love::Type type, const luaL_Reg *f, bool pu
|
||||
lua_pushcclosure(L, w__tostring, 1);
|
||||
lua_setfield(L, -2, "__tostring");
|
||||
|
||||
// Add tostring to as type() as well.
|
||||
// Add type
|
||||
lua_pushstring(L, tname);
|
||||
lua_pushcclosure(L, w__tostring, 1);
|
||||
lua_pushcclosure(L, w__type, 1);
|
||||
lua_setfield(L, -2, "type");
|
||||
|
||||
// Add typeOf
|
||||
@@ -590,8 +598,6 @@ int luax_insistregistry(lua_State *L, Registry r)
|
||||
{
|
||||
switch (r)
|
||||
{
|
||||
case REGISTRY_GC:
|
||||
return luax_insistlove(L, "_gc");
|
||||
case REGISTRY_MODULES:
|
||||
return luax_insistlove(L, "_modules");
|
||||
case REGISTRY_OBJECTS:
|
||||
@@ -605,8 +611,6 @@ int luax_getregistry(lua_State *L, Registry r)
|
||||
{
|
||||
switch (r)
|
||||
{
|
||||
case REGISTRY_GC:
|
||||
return luax_getlove(L, "_gc");
|
||||
case REGISTRY_MODULES:
|
||||
return luax_getlove(L, "_modules");
|
||||
case REGISTRY_OBJECTS:
|
||||
@@ -617,21 +621,54 @@ int luax_getregistry(lua_State *L, Registry r)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *MAIN_THREAD_KEY = "_love_mainthread";
|
||||
|
||||
lua_State *luax_insistpinnedthread(lua_State *L)
|
||||
{
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, MAIN_THREAD_KEY);
|
||||
|
||||
if (lua_isnoneornil(L, -1))
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
|
||||
// lua_pushthread returns 1 if it's actually the main thread, but we
|
||||
// can't actually get the real main thread if lua_pushthread doesn't
|
||||
// return it (in Lua 5.1 at least), so we ignore that for now...
|
||||
// We do store a strong reference to the current thread/coroutine in
|
||||
// the registry, however.
|
||||
lua_pushthread(L);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, MAIN_THREAD_KEY);
|
||||
}
|
||||
|
||||
lua_State *thread = lua_tothread(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return thread;
|
||||
}
|
||||
|
||||
lua_State *luax_getpinnedthread(lua_State *L)
|
||||
{
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, MAIN_THREAD_KEY);
|
||||
lua_State *thread = lua_tothread(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return thread;
|
||||
}
|
||||
|
||||
extern "C" int luax_typerror(lua_State *L, int narg, const char *tname)
|
||||
{
|
||||
int argtype = lua_type(L, narg);
|
||||
const char *argtname = 0;
|
||||
|
||||
// We want to use the love type name for userdata, if possible.
|
||||
if (argtype == LUA_TUSERDATA && luaL_getmetafield(L, narg, "__tostring") != 0)
|
||||
if (argtype == LUA_TUSERDATA && luaL_getmetafield(L, narg, "type") != 0)
|
||||
{
|
||||
lua_pushvalue(L, narg);
|
||||
if (lua_pcall(L, 1, 1, 0) == 0 && lua_type(L, -1) == LUA_TSTRING)
|
||||
{
|
||||
argtname = lua_tostring(L, -1);
|
||||
|
||||
// Non-love userdata might have a tostring metamethod which doesn't
|
||||
// describe its type, so we only use __tostring for love types.
|
||||
// Non-love userdata might have a type metamethod which doesn't
|
||||
// describe its type properly, so we only use it for love types.
|
||||
love::Type t;
|
||||
if (!love::getType(argtname, t))
|
||||
argtname = 0;
|
||||
|
||||
@@ -49,7 +49,6 @@ class Reference;
|
||||
**/
|
||||
enum Registry
|
||||
{
|
||||
REGISTRY_GC,
|
||||
REGISTRY_MODULES,
|
||||
REGISTRY_OBJECTS
|
||||
};
|
||||
@@ -390,6 +389,24 @@ int luax_insistregistry(lua_State *L, Registry r);
|
||||
**/
|
||||
int luax_getregistry(lua_State *L, Registry r);
|
||||
|
||||
/**
|
||||
* Gets (and pins if needed) a "pinned" Lua thread (coroutine) in the specified
|
||||
* Lua state. This will usually be the main Lua thread, unless the first call
|
||||
* to this function for a specific Lua state is made from within a coroutine.
|
||||
* NOTE: This does not push anything to the stack.
|
||||
**/
|
||||
lua_State *luax_insistpinnedthread(lua_State *L);
|
||||
|
||||
/**
|
||||
* Gets a "pinned" Lua thread (coroutine) in the specified Lua state. This will
|
||||
* usually be the main Lua thread. This can be used to access global variables
|
||||
* in a specific Lua state without needing another alive lua_State value.
|
||||
* PRECONDITION: luax_insistpinnedthread must have been called on a lua_State
|
||||
* value corresponding to the Lua state which will be used with this function.
|
||||
* NOTE: This does not push anything to the stack.
|
||||
**/
|
||||
lua_State *luax_getpinnedthread(lua_State *L);
|
||||
|
||||
extern "C" { // Also called from luasocket
|
||||
int luax_typerror(lua_State *L, int narg, const char *tname);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user