Switch from Nz prefix to namespace Nz
What a huge commit Former-commit-id: 38ac5eebf70adc1180f571f6006192d28fb99897
This commit is contained in:
@@ -11,20 +11,23 @@
|
||||
#include <Nazara/Core/Initializer.hpp>
|
||||
#include <Nazara/Lua/Config.hpp>
|
||||
|
||||
class NAZARA_LUA_API NzLua
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzLua() = delete;
|
||||
~NzLua() = delete;
|
||||
class NAZARA_LUA_API Lua
|
||||
{
|
||||
public:
|
||||
Lua() = delete;
|
||||
~Lua() = delete;
|
||||
|
||||
static bool Initialize();
|
||||
static bool Initialize();
|
||||
|
||||
static bool IsInitialized();
|
||||
static bool IsInitialized();
|
||||
|
||||
static void Uninitialize();
|
||||
static void Uninitialize();
|
||||
|
||||
private:
|
||||
static unsigned int s_moduleReferenceCounter;
|
||||
};
|
||||
private:
|
||||
static unsigned int s_moduleReferenceCounter;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_LUA_HPP
|
||||
|
||||
@@ -14,65 +14,68 @@
|
||||
#include <memory>
|
||||
//#include <type_traits>
|
||||
|
||||
template<class T/*, class P = void*/>
|
||||
class NzLuaClass
|
||||
namespace Nz
|
||||
{
|
||||
//static_assert(std::is_same<P, void>::value || std::is_base_of<P, T>::value, "P must be a base of T");
|
||||
template<class T/*, class P = void*/>
|
||||
class LuaClass
|
||||
{
|
||||
//static_assert(std::is_same<P, void>::value || std::is_base_of<P, T>::value, "P must be a base of T");
|
||||
|
||||
public:
|
||||
using ClassFunc = int (*)(NzLuaInstance& lua, T& instance);
|
||||
using ClassIndexFunc = bool (*)(NzLuaInstance& lua, T& instance);
|
||||
using ConstructorFunc = T* (*)(NzLuaInstance& lua);
|
||||
using FinalizerFunc = bool (*)(NzLuaInstance& lua, T& instance);
|
||||
using StaticIndexFunc = bool (*)(NzLuaInstance& lua);
|
||||
using StaticFunc = int (*)(NzLuaInstance& lua);
|
||||
public:
|
||||
using ClassFunc = int (*)(LuaInstance& lua, T& instance);
|
||||
using ClassIndexFunc = bool (*)(LuaInstance& lua, T& instance);
|
||||
using ConstructorFunc = T* (*)(LuaInstance& lua);
|
||||
using FinalizerFunc = bool (*)(LuaInstance& lua, T& instance);
|
||||
using StaticIndexFunc = bool (*)(LuaInstance& lua);
|
||||
using StaticFunc = int (*)(LuaInstance& lua);
|
||||
|
||||
NzLuaClass(const NzString& name);
|
||||
LuaClass(const String& name);
|
||||
|
||||
//void Inherit(NzLuaClass<P>& parent);
|
||||
//void Inherit(LuaClass<P>& parent);
|
||||
|
||||
void Register(NzLuaInstance& lua);
|
||||
void Register(LuaInstance& lua);
|
||||
|
||||
void PushGlobalTable(NzLuaInstance& lua);
|
||||
void PushGlobalTable(LuaInstance& lua);
|
||||
|
||||
void SetConstructor(ConstructorFunc constructor);
|
||||
void SetFinalizer(FinalizerFunc finalizer);
|
||||
void SetGetter(ClassIndexFunc getter);
|
||||
void SetMethod(const NzString& name, ClassFunc method);
|
||||
void SetSetter(ClassIndexFunc setter);
|
||||
void SetStaticGetter(StaticIndexFunc getter);
|
||||
void SetStaticMethod(const NzString& name, StaticFunc func);
|
||||
void SetStaticSetter(StaticIndexFunc getter);
|
||||
void SetConstructor(ConstructorFunc constructor);
|
||||
void SetFinalizer(FinalizerFunc finalizer);
|
||||
void SetGetter(ClassIndexFunc getter);
|
||||
void SetMethod(const String& name, ClassFunc method);
|
||||
void SetSetter(ClassIndexFunc setter);
|
||||
void SetStaticGetter(StaticIndexFunc getter);
|
||||
void SetStaticMethod(const String& name, StaticFunc func);
|
||||
void SetStaticSetter(StaticIndexFunc getter);
|
||||
|
||||
private:
|
||||
static int ConstructorProxy(lua_State* state);
|
||||
static int FinalizerProxy(lua_State* state);
|
||||
static int InfoDestructor(lua_State* state);
|
||||
static int GetterProxy(lua_State* state);
|
||||
static int MethodProxy(lua_State* state);
|
||||
static int SetterProxy(lua_State* state);
|
||||
static int StaticGetterProxy(lua_State* state);
|
||||
static int StaticMethodProxy(lua_State* state);
|
||||
static int StaticSetterProxy(lua_State* state);
|
||||
private:
|
||||
static int ConstructorProxy(lua_State* state);
|
||||
static int FinalizerProxy(lua_State* state);
|
||||
static int InfoDestructor(lua_State* state);
|
||||
static int GetterProxy(lua_State* state);
|
||||
static int MethodProxy(lua_State* state);
|
||||
static int SetterProxy(lua_State* state);
|
||||
static int StaticGetterProxy(lua_State* state);
|
||||
static int StaticMethodProxy(lua_State* state);
|
||||
static int StaticSetterProxy(lua_State* state);
|
||||
|
||||
struct ClassInfo
|
||||
{
|
||||
std::vector<ClassFunc> methods;
|
||||
std::vector<StaticFunc> staticMethods;
|
||||
ClassIndexFunc getter = nullptr;
|
||||
ClassIndexFunc setter = nullptr;
|
||||
ConstructorFunc constructor = nullptr;
|
||||
FinalizerFunc finalizer = nullptr;
|
||||
StaticIndexFunc staticGetter = nullptr;
|
||||
StaticIndexFunc staticSetter = nullptr;
|
||||
NzString name;
|
||||
int globalTableRef = -1;
|
||||
};
|
||||
struct ClassInfo
|
||||
{
|
||||
std::vector<ClassFunc> methods;
|
||||
std::vector<StaticFunc> staticMethods;
|
||||
ClassIndexFunc getter = nullptr;
|
||||
ClassIndexFunc setter = nullptr;
|
||||
ConstructorFunc constructor = nullptr;
|
||||
FinalizerFunc finalizer = nullptr;
|
||||
StaticIndexFunc staticGetter = nullptr;
|
||||
StaticIndexFunc staticSetter = nullptr;
|
||||
String name;
|
||||
int globalTableRef = -1;
|
||||
};
|
||||
|
||||
std::map<NzString, ClassFunc> m_methods;
|
||||
std::map<NzString, StaticFunc> m_staticMethods;
|
||||
std::shared_ptr<ClassInfo> m_info;
|
||||
};
|
||||
std::map<String, ClassFunc> m_methods;
|
||||
std::map<String, StaticFunc> m_staticMethods;
|
||||
std::shared_ptr<ClassInfo> m_info;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Lua/LuaClass.inl>
|
||||
|
||||
|
||||
@@ -6,357 +6,360 @@
|
||||
#include <Nazara/Core/MemoryHelper.hpp>
|
||||
#include <Nazara/Lua/Debug.hpp>
|
||||
|
||||
template<class T>
|
||||
NzLuaClass<T>::NzLuaClass(const NzString& name) :
|
||||
m_info(new ClassInfo)
|
||||
namespace Nz
|
||||
{
|
||||
m_info->name = name;
|
||||
}
|
||||
/*
|
||||
template<class T>
|
||||
void NzLuaClass<T>::Inherit(NzLuaClass<P>& parent)
|
||||
{
|
||||
static_assert(std::is_base_of<P, T>::value, "P must be a base of T");
|
||||
|
||||
m_info->parentInfo = parent.m_info;
|
||||
}
|
||||
*/
|
||||
template<class T>
|
||||
void NzLuaClass<T>::Register(NzLuaInstance& lua)
|
||||
{
|
||||
// Le ClassInfo doit rester en vie jusqu'à la fin du script
|
||||
// Obliger l'instance de LuaClass à rester en vie dans cette fin serait contraignant pour l'utilisateur
|
||||
// J'utilise donc une astuce, la stocker dans une UserData associée avec chaque fonction de la metatable du type,
|
||||
// cette UserData disposera d'un finalizer qui libérera le ClassInfo
|
||||
// Ainsi c'est Lua qui va s'occuper de la destruction pour nous :-)
|
||||
// De même, l'utilisation d'un shared_ptr permet de garder la structure en vie même si l'instance est libérée avant le LuaClass
|
||||
void* info = lua.PushUserdata(sizeof(std::shared_ptr<ClassInfo>));
|
||||
NzPlacementNew<std::shared_ptr<ClassInfo>>(info, m_info);
|
||||
|
||||
// On créé la table qui contiendra une méthode (Le finalizer) pour libérer le ClassInfo
|
||||
lua.PushTable(0, 1);
|
||||
lua.PushLightUserdata(info);
|
||||
lua.PushCFunction(InfoDestructor, 1);
|
||||
lua.SetField("__gc");
|
||||
lua.SetMetatable(-2); // La table devient la metatable de l'UserData
|
||||
|
||||
// Maintenant, nous allons associer l'UserData avec chaque fonction, de sorte qu'il reste en vie
|
||||
// aussi longtemps que nécessaire, et que le pointeur soit transmis à chaque méthode
|
||||
|
||||
if (!lua.NewMetatable(m_info->name))
|
||||
NazaraWarning("Class \"" + m_info->name + "\" already registred in this instance");
|
||||
template<class T>
|
||||
LuaClass<T>::LuaClass(const String& name) :
|
||||
m_info(new ClassInfo)
|
||||
{
|
||||
lua.PushValue(1); // On associe l'UserData avec la fonction
|
||||
lua.PushCFunction(FinalizerProxy, 1);
|
||||
lua.SetField("__gc"); // Finalizer
|
||||
m_info->name = name;
|
||||
}
|
||||
/*
|
||||
template<class T>
|
||||
void LuaClass<T>::Inherit(LuaClass<P>& parent)
|
||||
{
|
||||
static_assert(std::is_base_of<P, T>::value, "P must be a base of T");
|
||||
|
||||
if (m_info->getter)
|
||||
m_info->parentInfo = parent.m_info;
|
||||
}
|
||||
*/
|
||||
template<class T>
|
||||
void LuaClass<T>::Register(LuaInstance& lua)
|
||||
{
|
||||
// Le ClassInfo doit rester en vie jusqu'à la fin du script
|
||||
// Obliger l'instance de LuaClass à rester en vie dans cette fin serait contraignant pour l'utilisateur
|
||||
// J'utilise donc une astuce, la stocker dans une UserData associée avec chaque fonction de la metatable du type,
|
||||
// cette UserData disposera d'un finalizer qui libérera le ClassInfo
|
||||
// Ainsi c'est Lua qui va s'occuper de la destruction pour nous :-)
|
||||
// De même, l'utilisation d'un shared_ptr permet de garder la structure en vie même si l'instance est libérée avant le LuaClass
|
||||
void* info = lua.PushUserdata(sizeof(std::shared_ptr<ClassInfo>));
|
||||
PlacementNew<std::shared_ptr<ClassInfo>>(info, m_info);
|
||||
|
||||
// On créé la table qui contiendra une méthode (Le finalizer) pour libérer le ClassInfo
|
||||
lua.PushTable(0, 1);
|
||||
lua.PushLightUserdata(info);
|
||||
lua.PushCFunction(InfoDestructor, 1);
|
||||
lua.SetField("__gc");
|
||||
lua.SetMetatable(-2); // La table devient la metatable de l'UserData
|
||||
|
||||
// Maintenant, nous allons associer l'UserData avec chaque fonction, de sorte qu'il reste en vie
|
||||
// aussi longtemps que nécessaire, et que le pointeur soit transmis à chaque méthode
|
||||
|
||||
if (!lua.NewMetatable(m_info->name))
|
||||
NazaraWarning("Class \"" + m_info->name + "\" already registred in this instance");
|
||||
{
|
||||
lua.PushValue(1);
|
||||
lua.PushValue(1); // On associe l'UserData avec la fonction
|
||||
lua.PushCFunction(FinalizerProxy, 1);
|
||||
lua.SetField("__gc"); // Finalizer
|
||||
|
||||
if (m_info->getter)
|
||||
{
|
||||
lua.PushValue(1);
|
||||
lua.PushValue(-2);
|
||||
lua.PushCFunction(GetterProxy, 2);
|
||||
}
|
||||
else
|
||||
// Optimisation, plutôt que de rediriger vers une fonction C qui ne fera rien d'autre que rechercher
|
||||
// dans la table, nous envoyons directement la table, de sorte que Lua fasse directement la recherche
|
||||
// Ceci n'est possible que si nous n'avons ni getter, ni parent
|
||||
lua.PushValue(-1);
|
||||
|
||||
lua.SetField("__index"); // Getter
|
||||
|
||||
if (m_info->setter)
|
||||
{
|
||||
lua.PushValue(1);
|
||||
lua.PushCFunction(SetterProxy, 1);
|
||||
lua.SetField("__newindex"); // Setter
|
||||
}
|
||||
|
||||
m_info->methods.reserve(m_methods.size());
|
||||
for (auto& pair : m_methods)
|
||||
{
|
||||
m_info->methods.push_back(pair.second);
|
||||
|
||||
lua.PushValue(1);
|
||||
lua.PushInteger(m_info->methods.size() - 1);
|
||||
|
||||
lua.PushCFunction(MethodProxy, 2);
|
||||
lua.SetField(pair.first); // Méthode
|
||||
}
|
||||
}
|
||||
lua.Pop(); // On pop la metatable
|
||||
|
||||
if (m_info->constructor || m_info->staticGetter || m_info->staticSetter || !m_info->staticMethods.empty())
|
||||
{
|
||||
// Création de l'instance globale
|
||||
lua.PushTable(); // Class = {}
|
||||
|
||||
// Création de la metatable associée à la table globale
|
||||
lua.PushTable(); // ClassMeta = {}
|
||||
|
||||
if (m_info->constructor)
|
||||
{
|
||||
lua.PushValue(1); // ClassInfo
|
||||
lua.PushCFunction(ConstructorProxy, 1);
|
||||
lua.SetField("__call"); // ClassMeta.__call = ConstructorProxy
|
||||
}
|
||||
|
||||
if (m_info->staticGetter)
|
||||
{
|
||||
lua.PushValue(1);
|
||||
lua.PushValue(-2);
|
||||
lua.PushCFunction(StaticGetterProxy, 2);
|
||||
}
|
||||
else
|
||||
// Optimisation, plutôt que de rediriger vers une fonction C qui ne fera rien d'autre que rechercher
|
||||
// dans la table, nous envoyons directement la table, de sorte que Lua fasse directement la recherche
|
||||
// Ceci n'est possible que si nous n'avons ni getter, ni parent
|
||||
lua.PushValue(-1);
|
||||
|
||||
lua.SetField("__index"); // ClassMeta.__index = StaticGetterProxy/ClassMeta
|
||||
|
||||
if (m_info->staticSetter)
|
||||
{
|
||||
lua.PushValue(1);
|
||||
lua.PushCFunction(StaticSetterProxy, 1);
|
||||
lua.SetField("__newindex"); // ClassMeta.__newindex = StaticSetterProxy
|
||||
}
|
||||
|
||||
m_info->staticMethods.reserve(m_staticMethods.size());
|
||||
for (auto& pair : m_staticMethods)
|
||||
{
|
||||
m_info->staticMethods.push_back(pair.second);
|
||||
|
||||
lua.PushValue(1);
|
||||
lua.PushInteger(m_info->staticMethods.size() - 1);
|
||||
|
||||
lua.PushCFunction(StaticMethodProxy, 2);
|
||||
lua.SetField(pair.first); // ClassMeta.method = StaticMethodProxy
|
||||
}
|
||||
|
||||
lua.SetMetatable(-2); // setmetatable(Class, ClassMeta)
|
||||
|
||||
lua.PushValue(-1); // Copie
|
||||
lua.SetGlobal(m_info->name); // Class
|
||||
|
||||
m_info->globalTableRef = lua.CreateReference();
|
||||
}
|
||||
lua.Pop(); // On pop l'Userdata (contenant nos informations)
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::PushGlobalTable(LuaInstance& lua)
|
||||
{
|
||||
lua.PushReference(m_info->globalTableRef);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetConstructor(ConstructorFunc constructor)
|
||||
{
|
||||
m_info->constructor = constructor;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetFinalizer(FinalizerFunc finalizer)
|
||||
{
|
||||
m_info->finalizer = finalizer;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetGetter(ClassIndexFunc getter)
|
||||
{
|
||||
m_info->getter = getter;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetMethod(const String& name, ClassFunc method)
|
||||
{
|
||||
m_methods[name] = method;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetSetter(ClassIndexFunc setter)
|
||||
{
|
||||
m_info->setter = setter;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetStaticGetter(StaticIndexFunc getter)
|
||||
{
|
||||
m_info->staticGetter = getter;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetStaticMethod(const String& name, StaticFunc method)
|
||||
{
|
||||
m_staticMethods[name] = method;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetStaticSetter(StaticIndexFunc setter)
|
||||
{
|
||||
m_info->staticSetter = setter;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::ConstructorProxy(lua_State* state)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
ConstructorFunc constructor = info->constructor;
|
||||
|
||||
lua.Remove(1); // On enlève l'argument "table" du stack
|
||||
|
||||
T* instance = constructor(lua);
|
||||
if (!instance)
|
||||
{
|
||||
lua.Error("Constructor failed");
|
||||
return 0; // Normalement jamais exécuté (l'erreur provoquant une exception)
|
||||
}
|
||||
|
||||
T** ud = static_cast<T**>(lua.PushUserdata(sizeof(T*)));
|
||||
*ud = instance;
|
||||
lua.SetMetatable(info->name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::FinalizerProxy(lua_State* state)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
FinalizerFunc finalizer = info->finalizer;
|
||||
|
||||
T* instance = *static_cast<T**>(lua.CheckUserdata(1, info->name));
|
||||
|
||||
if (!finalizer || finalizer(lua, *instance))
|
||||
delete instance;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::InfoDestructor(lua_State* state)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
|
||||
std::shared_ptr<ClassInfo>& infoPtr = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
lua.DestroyReference(infoPtr->globalTableRef);
|
||||
|
||||
using namespace std; // Obligatoire pour le destructeur
|
||||
infoPtr.~shared_ptr(); // Si vous voyez une autre façon de faire, je suis preneur
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::GetterProxy(lua_State* state)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
ClassIndexFunc getter = info->getter;
|
||||
|
||||
T& instance = *(*static_cast<T**>(lua.CheckUserdata(1, info->name)));
|
||||
|
||||
if (!getter(lua, instance))
|
||||
{
|
||||
// On accède alors à la table
|
||||
lua.PushValue(lua.GetIndexOfUpValue(2));
|
||||
lua.PushValue(-2);
|
||||
lua.PushCFunction(GetterProxy, 2);
|
||||
}
|
||||
else
|
||||
// Optimisation, plutôt que de rediriger vers une fonction C qui ne fera rien d'autre que rechercher
|
||||
// dans la table, nous envoyons directement la table, de sorte que Lua fasse directement la recherche
|
||||
// Ceci n'est possible que si nous n'avons ni getter, ni parent
|
||||
lua.PushValue(-1);
|
||||
|
||||
lua.SetField("__index"); // Getter
|
||||
|
||||
if (m_info->setter)
|
||||
{
|
||||
lua.PushValue(1);
|
||||
lua.PushCFunction(SetterProxy, 1);
|
||||
lua.SetField("__newindex"); // Setter
|
||||
lua.GetTable();
|
||||
}
|
||||
|
||||
m_info->methods.reserve(m_methods.size());
|
||||
for (auto& pair : m_methods)
|
||||
{
|
||||
m_info->methods.push_back(pair.second);
|
||||
|
||||
lua.PushValue(1);
|
||||
lua.PushInteger(m_info->methods.size() - 1);
|
||||
|
||||
lua.PushCFunction(MethodProxy, 2);
|
||||
lua.SetField(pair.first); // Méthode
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
lua.Pop(); // On pop la metatable
|
||||
|
||||
if (m_info->constructor || m_info->staticGetter || m_info->staticSetter || !m_info->staticMethods.empty())
|
||||
template<class T>
|
||||
int LuaClass<T>::MethodProxy(lua_State* state)
|
||||
{
|
||||
// Création de l'instance globale
|
||||
lua.PushTable(); // Class = {}
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
|
||||
// Création de la metatable associée à la table globale
|
||||
lua.PushTable(); // ClassMeta = {}
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
unsigned int index = static_cast<unsigned int>(lua.ToInteger(lua.GetIndexOfUpValue(2)));
|
||||
ClassFunc method = info->methods[index];
|
||||
|
||||
if (m_info->constructor)
|
||||
T& instance = *(*static_cast<T**>(lua.CheckUserdata(1, info->name)));
|
||||
|
||||
lua.Remove(1); // On enlève l'argument "userdata" du stack
|
||||
|
||||
return method(lua, instance);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::SetterProxy(lua_State* state)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
ClassIndexFunc setter = info->setter;
|
||||
|
||||
T& instance = *(*static_cast<T**>(lua.CheckUserdata(1, info->name)));
|
||||
|
||||
if (!setter(lua, instance))
|
||||
{
|
||||
lua.PushValue(1); // ClassInfo
|
||||
lua.PushCFunction(ConstructorProxy, 1);
|
||||
lua.SetField("__call"); // ClassMeta.__call = ConstructorProxy
|
||||
std::size_t length;
|
||||
const char* str = lua.ToString(2, &length);
|
||||
|
||||
lua.Error("Class \"" + info->name + "\" has no field \"" + String(str, length) + ')');
|
||||
}
|
||||
|
||||
if (m_info->staticGetter)
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::StaticGetterProxy(lua_State* state)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
StaticIndexFunc getter = info->staticGetter;
|
||||
|
||||
if (!getter(lua))
|
||||
{
|
||||
lua.PushValue(1);
|
||||
// On accède alors à la table
|
||||
lua.PushValue(lua.GetIndexOfUpValue(2));
|
||||
lua.PushValue(-2);
|
||||
lua.PushCFunction(StaticGetterProxy, 2);
|
||||
lua.GetTable();
|
||||
}
|
||||
else
|
||||
// Optimisation, plutôt que de rediriger vers une fonction C qui ne fera rien d'autre que rechercher
|
||||
// dans la table, nous envoyons directement la table, de sorte que Lua fasse directement la recherche
|
||||
// Ceci n'est possible que si nous n'avons ni getter, ni parent
|
||||
lua.PushValue(-1);
|
||||
|
||||
lua.SetField("__index"); // ClassMeta.__index = StaticGetterProxy/ClassMeta
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (m_info->staticSetter)
|
||||
template<class T>
|
||||
int LuaClass<T>::StaticMethodProxy(lua_State* state)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
unsigned int index = static_cast<unsigned int>(lua.ToInteger(lua.GetIndexOfUpValue(2)));
|
||||
StaticFunc method = info->staticMethods[index];
|
||||
|
||||
return method(lua);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::StaticSetterProxy(lua_State* state)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
StaticIndexFunc setter = info->staticSetter;
|
||||
|
||||
if (!setter(lua))
|
||||
{
|
||||
lua.PushValue(1);
|
||||
lua.PushCFunction(StaticSetterProxy, 1);
|
||||
lua.SetField("__newindex"); // ClassMeta.__newindex = StaticSetterProxy
|
||||
std::size_t length;
|
||||
const char* str = lua.ToString(2, &length);
|
||||
|
||||
lua.Error("Class \"" + info->name + "\" has no static field \"" + String(str, length) + ')');
|
||||
}
|
||||
|
||||
m_info->staticMethods.reserve(m_staticMethods.size());
|
||||
for (auto& pair : m_staticMethods)
|
||||
{
|
||||
m_info->staticMethods.push_back(pair.second);
|
||||
|
||||
lua.PushValue(1);
|
||||
lua.PushInteger(m_info->staticMethods.size() - 1);
|
||||
|
||||
lua.PushCFunction(StaticMethodProxy, 2);
|
||||
lua.SetField(pair.first); // ClassMeta.method = StaticMethodProxy
|
||||
}
|
||||
|
||||
lua.SetMetatable(-2); // setmetatable(Class, ClassMeta)
|
||||
|
||||
lua.PushValue(-1); // Copie
|
||||
lua.SetGlobal(m_info->name); // Class
|
||||
|
||||
m_info->globalTableRef = lua.CreateReference();
|
||||
return 1;
|
||||
}
|
||||
lua.Pop(); // On pop l'Userdata (contenant nos informations)
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void NzLuaClass<T>::PushGlobalTable(NzLuaInstance& lua)
|
||||
{
|
||||
lua.PushReference(m_info->globalTableRef);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void NzLuaClass<T>::SetConstructor(ConstructorFunc constructor)
|
||||
{
|
||||
m_info->constructor = constructor;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void NzLuaClass<T>::SetFinalizer(FinalizerFunc finalizer)
|
||||
{
|
||||
m_info->finalizer = finalizer;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void NzLuaClass<T>::SetGetter(ClassIndexFunc getter)
|
||||
{
|
||||
m_info->getter = getter;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void NzLuaClass<T>::SetMethod(const NzString& name, ClassFunc method)
|
||||
{
|
||||
m_methods[name] = method;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void NzLuaClass<T>::SetSetter(ClassIndexFunc setter)
|
||||
{
|
||||
m_info->setter = setter;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void NzLuaClass<T>::SetStaticGetter(StaticIndexFunc getter)
|
||||
{
|
||||
m_info->staticGetter = getter;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void NzLuaClass<T>::SetStaticMethod(const NzString& name, StaticFunc method)
|
||||
{
|
||||
m_staticMethods[name] = method;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void NzLuaClass<T>::SetStaticSetter(StaticIndexFunc setter)
|
||||
{
|
||||
m_info->staticSetter = setter;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int NzLuaClass<T>::ConstructorProxy(lua_State* state)
|
||||
{
|
||||
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
ConstructorFunc constructor = info->constructor;
|
||||
|
||||
lua.Remove(1); // On enlève l'argument "table" du stack
|
||||
|
||||
T* instance = constructor(lua);
|
||||
if (!instance)
|
||||
{
|
||||
lua.Error("Constructor failed");
|
||||
return 0; // Normalement jamais exécuté (l'erreur provoquant une exception)
|
||||
}
|
||||
|
||||
T** ud = static_cast<T**>(lua.PushUserdata(sizeof(T*)));
|
||||
*ud = instance;
|
||||
lua.SetMetatable(info->name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int NzLuaClass<T>::FinalizerProxy(lua_State* state)
|
||||
{
|
||||
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
FinalizerFunc finalizer = info->finalizer;
|
||||
|
||||
T* instance = *static_cast<T**>(lua.CheckUserdata(1, info->name));
|
||||
|
||||
if (!finalizer || finalizer(lua, *instance))
|
||||
delete instance;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int NzLuaClass<T>::InfoDestructor(lua_State* state)
|
||||
{
|
||||
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
|
||||
|
||||
std::shared_ptr<ClassInfo>& infoPtr = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
lua.DestroyReference(infoPtr->globalTableRef);
|
||||
|
||||
using namespace std; // Obligatoire pour le destructeur
|
||||
infoPtr.~shared_ptr(); // Si vous voyez une autre façon de faire, je suis preneur
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int NzLuaClass<T>::GetterProxy(lua_State* state)
|
||||
{
|
||||
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
ClassIndexFunc getter = info->getter;
|
||||
|
||||
T& instance = *(*static_cast<T**>(lua.CheckUserdata(1, info->name)));
|
||||
|
||||
if (!getter(lua, instance))
|
||||
{
|
||||
// On accède alors à la table
|
||||
lua.PushValue(lua.GetIndexOfUpValue(2));
|
||||
lua.PushValue(-2);
|
||||
lua.GetTable();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int NzLuaClass<T>::MethodProxy(lua_State* state)
|
||||
{
|
||||
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
unsigned int index = static_cast<unsigned int>(lua.ToInteger(lua.GetIndexOfUpValue(2)));
|
||||
ClassFunc method = info->methods[index];
|
||||
|
||||
T& instance = *(*static_cast<T**>(lua.CheckUserdata(1, info->name)));
|
||||
|
||||
lua.Remove(1); // On enlève l'argument "userdata" du stack
|
||||
|
||||
return method(lua, instance);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int NzLuaClass<T>::SetterProxy(lua_State* state)
|
||||
{
|
||||
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
ClassIndexFunc setter = info->setter;
|
||||
|
||||
T& instance = *(*static_cast<T**>(lua.CheckUserdata(1, info->name)));
|
||||
|
||||
if (!setter(lua, instance))
|
||||
{
|
||||
std::size_t length;
|
||||
const char* str = lua.ToString(2, &length);
|
||||
|
||||
lua.Error("Class \"" + info->name + "\" has no field \"" + NzString(str, length) + ')');
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int NzLuaClass<T>::StaticGetterProxy(lua_State* state)
|
||||
{
|
||||
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
StaticIndexFunc getter = info->staticGetter;
|
||||
|
||||
if (!getter(lua))
|
||||
{
|
||||
// On accède alors à la table
|
||||
lua.PushValue(lua.GetIndexOfUpValue(2));
|
||||
lua.PushValue(-2);
|
||||
lua.GetTable();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int NzLuaClass<T>::StaticMethodProxy(lua_State* state)
|
||||
{
|
||||
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
unsigned int index = static_cast<unsigned int>(lua.ToInteger(lua.GetIndexOfUpValue(2)));
|
||||
StaticFunc method = info->staticMethods[index];
|
||||
|
||||
return method(lua);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int NzLuaClass<T>::StaticSetterProxy(lua_State* state)
|
||||
{
|
||||
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
|
||||
|
||||
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
StaticIndexFunc setter = info->staticSetter;
|
||||
|
||||
if (!setter(lua))
|
||||
{
|
||||
std::size_t length;
|
||||
const char* str = lua.ToString(2, &length);
|
||||
|
||||
lua.Error("Class \"" + info->name + "\" has no static field \"" + NzString(str, length) + ')');
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#include <Nazara/Lua/DebugOff.hpp>
|
||||
|
||||
@@ -19,157 +19,160 @@
|
||||
struct lua_Debug;
|
||||
struct lua_State;
|
||||
|
||||
class NzLuaInstance;
|
||||
|
||||
using NzLuaCFunction = int (*)(lua_State* state);
|
||||
using NzLuaFunction = std::function<int(NzLuaInstance& instance)>;
|
||||
|
||||
class NAZARA_LUA_API NzLuaInstance
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzLuaInstance();
|
||||
NzLuaInstance(const NzLuaInstance&) = delete;
|
||||
NzLuaInstance(NzLuaInstance&&) = delete; ///TODO
|
||||
~NzLuaInstance();
|
||||
class LuaInstance;
|
||||
|
||||
void ArgCheck(bool condition, unsigned int argNum, const char* error);
|
||||
void ArgCheck(bool condition, unsigned int argNum, const NzString& error);
|
||||
int ArgError(unsigned int argNum, const char* error);
|
||||
int ArgError(unsigned int argNum, const NzString& error);
|
||||
using LuaCFunction = int (*)(lua_State* state);
|
||||
using LuaFunction = std::function<int(LuaInstance& instance)>;
|
||||
|
||||
bool Call(unsigned int argCount);
|
||||
bool Call(unsigned int argCount, unsigned int resultCount);
|
||||
class NAZARA_LUA_API LuaInstance
|
||||
{
|
||||
public:
|
||||
LuaInstance();
|
||||
LuaInstance(const LuaInstance&) = delete;
|
||||
LuaInstance(LuaInstance&&) = delete; ///TODO
|
||||
~LuaInstance();
|
||||
|
||||
void CheckAny(int index) const;
|
||||
bool CheckBoolean(int index) const;
|
||||
bool CheckBoolean(int index, bool defValue) const;
|
||||
long long CheckInteger(int index) const;
|
||||
long long CheckInteger(int index, long long defValue) const;
|
||||
double CheckNumber(int index) const;
|
||||
double CheckNumber(int index, double defValue) const;
|
||||
void CheckStack(int space, const char* error = nullptr) const;
|
||||
void CheckStack(int space, const NzString& error) const;
|
||||
const char* CheckString(int index, std::size_t* length = nullptr) const;
|
||||
const char* CheckString(int index, const char* defValue, std::size_t* length = nullptr) const;
|
||||
void CheckType(int index, nzLuaType type) const;
|
||||
void* CheckUserdata(int index, const char* tname) const;
|
||||
void* CheckUserdata(int index, const NzString& tname) const;
|
||||
void ArgCheck(bool condition, unsigned int argNum, const char* error);
|
||||
void ArgCheck(bool condition, unsigned int argNum, const String& error);
|
||||
int ArgError(unsigned int argNum, const char* error);
|
||||
int ArgError(unsigned int argNum, const String& error);
|
||||
|
||||
bool Compare(int index1, int index2, nzLuaComparison comparison) const;
|
||||
void Compute(nzLuaOperation operation);
|
||||
bool Call(unsigned int argCount);
|
||||
bool Call(unsigned int argCount, unsigned int resultCount);
|
||||
|
||||
void Concatenate(int count);
|
||||
void CheckAny(int index) const;
|
||||
bool CheckBoolean(int index) const;
|
||||
bool CheckBoolean(int index, bool defValue) const;
|
||||
long long CheckInteger(int index) const;
|
||||
long long CheckInteger(int index, long long defValue) const;
|
||||
double CheckNumber(int index) const;
|
||||
double CheckNumber(int index, double defValue) const;
|
||||
void CheckStack(int space, const char* error = nullptr) const;
|
||||
void CheckStack(int space, const String& error) const;
|
||||
const char* CheckString(int index, std::size_t* length = nullptr) const;
|
||||
const char* CheckString(int index, const char* defValue, std::size_t* length = nullptr) const;
|
||||
void CheckType(int index, nzLuaType type) const;
|
||||
void* CheckUserdata(int index, const char* tname) const;
|
||||
void* CheckUserdata(int index, const String& tname) const;
|
||||
|
||||
int CreateReference();
|
||||
void DestroyReference(int ref);
|
||||
bool Compare(int index1, int index2, nzLuaComparison comparison) const;
|
||||
void Compute(nzLuaOperation operation);
|
||||
|
||||
NzString DumpStack() const;
|
||||
void Concatenate(int count);
|
||||
|
||||
void Error(const char* message);
|
||||
void Error(const NzString& message);
|
||||
int CreateReference();
|
||||
void DestroyReference(int ref);
|
||||
|
||||
bool Execute(const NzString& code);
|
||||
bool ExecuteFromFile(const NzString& filePath);
|
||||
bool ExecuteFromMemory(const void* data, unsigned int size);
|
||||
bool ExecuteFromStream(NzInputStream& stream);
|
||||
String DumpStack() const;
|
||||
|
||||
int GetAbsIndex(int index) const;
|
||||
nzLuaType GetField(const char* fieldName, int index = -1) const;
|
||||
nzLuaType GetField(const NzString& fieldName, int index = -1) const;
|
||||
nzLuaType GetGlobal(const char* name) const;
|
||||
nzLuaType GetGlobal(const NzString& name) const;
|
||||
lua_State* GetInternalState() const;
|
||||
NzString GetLastError() const;
|
||||
nzUInt32 GetMemoryLimit() const;
|
||||
nzUInt32 GetMemoryUsage() const;
|
||||
nzLuaType GetMetatable(const char* tname) const;
|
||||
nzLuaType GetMetatable(const NzString& tname) const;
|
||||
bool GetMetatable(int index) const;
|
||||
unsigned int GetStackTop() const;
|
||||
nzLuaType GetTable(int index = -2) const;
|
||||
nzUInt32 GetTimeLimit() const;
|
||||
nzLuaType GetType(int index) const;
|
||||
const char* GetTypeName(nzLuaType type) const;
|
||||
void Error(const char* message);
|
||||
void Error(const String& message);
|
||||
|
||||
void Insert(int index);
|
||||
bool Execute(const String& code);
|
||||
bool ExecuteFromFile(const String& filePath);
|
||||
bool ExecuteFromMemory(const void* data, unsigned int size);
|
||||
bool ExecuteFromStream(InputStream& stream);
|
||||
|
||||
bool IsOfType(int index, nzLuaType type) const;
|
||||
bool IsOfType(int index, const char* tname) const;
|
||||
bool IsOfType(int index, const NzString& tname) const;
|
||||
bool IsValid(int index) const;
|
||||
int GetAbsIndex(int index) const;
|
||||
nzLuaType GetField(const char* fieldName, int index = -1) const;
|
||||
nzLuaType GetField(const String& fieldName, int index = -1) const;
|
||||
nzLuaType GetGlobal(const char* name) const;
|
||||
nzLuaType GetGlobal(const String& name) const;
|
||||
lua_State* GetInternalState() const;
|
||||
String GetLastError() const;
|
||||
UInt32 GetMemoryLimit() const;
|
||||
UInt32 GetMemoryUsage() const;
|
||||
nzLuaType GetMetatable(const char* tname) const;
|
||||
nzLuaType GetMetatable(const String& tname) const;
|
||||
bool GetMetatable(int index) const;
|
||||
unsigned int GetStackTop() const;
|
||||
nzLuaType GetTable(int index = -2) const;
|
||||
UInt32 GetTimeLimit() const;
|
||||
nzLuaType GetType(int index) const;
|
||||
const char* GetTypeName(nzLuaType type) const;
|
||||
|
||||
long long Length(int index) const;
|
||||
void Insert(int index);
|
||||
|
||||
void MoveTo(NzLuaInstance* instance, int n);
|
||||
bool IsOfType(int index, nzLuaType type) const;
|
||||
bool IsOfType(int index, const char* tname) const;
|
||||
bool IsOfType(int index, const String& tname) const;
|
||||
bool IsValid(int index) const;
|
||||
|
||||
bool NewMetatable(const char* str);
|
||||
bool NewMetatable(const NzString& str);
|
||||
bool Next(int index = -2);
|
||||
long long Length(int index) const;
|
||||
|
||||
void Pop(unsigned int n = 1U);
|
||||
void MoveTo(LuaInstance* instance, int n);
|
||||
|
||||
void PushBoolean(bool value);
|
||||
void PushCFunction(NzLuaCFunction func, unsigned int upvalueCount = 0);
|
||||
void PushFunction(NzLuaFunction func);
|
||||
template<typename R, typename... Args> void PushFunction(R(*func)(Args...));
|
||||
void PushInteger(long long value);
|
||||
void PushLightUserdata(void* value);
|
||||
void PushMetatable(const char* str);
|
||||
void PushMetatable(const NzString& str);
|
||||
void PushNil();
|
||||
void PushNumber(double value);
|
||||
void PushReference(int ref);
|
||||
void PushString(const char* str);
|
||||
void PushString(const char* str, unsigned int size);
|
||||
void PushString(const NzString& str);
|
||||
void PushTable(unsigned int sequenceElementCount = 0, unsigned int arrayElementCount = 0);
|
||||
void* PushUserdata(unsigned int size);
|
||||
void PushValue(int index);
|
||||
bool NewMetatable(const char* str);
|
||||
bool NewMetatable(const String& str);
|
||||
bool Next(int index = -2);
|
||||
|
||||
void Remove(int index);
|
||||
void Replace(int index);
|
||||
void Pop(unsigned int n = 1U);
|
||||
|
||||
void SetField(const char* name, int index = -2);
|
||||
void SetField(const NzString& name, int index = -2);
|
||||
void SetGlobal(const char* name);
|
||||
void SetGlobal(const NzString& name);
|
||||
void SetMetatable(const char* tname);
|
||||
void SetMetatable(const NzString& tname);
|
||||
void SetMetatable(int index);
|
||||
void SetMemoryLimit(nzUInt32 memoryLimit);
|
||||
void SetTable(int index = -3);
|
||||
void SetTimeLimit(nzUInt32 timeLimit);
|
||||
void PushBoolean(bool value);
|
||||
void PushCFunction(LuaCFunction func, unsigned int upvalueCount = 0);
|
||||
void PushFunction(LuaFunction func);
|
||||
template<typename R, typename... Args> void PushFunction(R(*func)(Args...));
|
||||
void PushInteger(long long value);
|
||||
void PushLightUserdata(void* value);
|
||||
void PushMetatable(const char* str);
|
||||
void PushMetatable(const String& str);
|
||||
void PushNil();
|
||||
void PushNumber(double value);
|
||||
void PushReference(int ref);
|
||||
void PushString(const char* str);
|
||||
void PushString(const char* str, unsigned int size);
|
||||
void PushString(const String& str);
|
||||
void PushTable(unsigned int sequenceElementCount = 0, unsigned int arrayElementCount = 0);
|
||||
void* PushUserdata(unsigned int size);
|
||||
void PushValue(int index);
|
||||
|
||||
bool ToBoolean(int index) const;
|
||||
long long ToInteger(int index, bool* succeeded = nullptr) const;
|
||||
double ToNumber(int index, bool* succeeded = nullptr) const;
|
||||
const void* ToPointer(int index) const;
|
||||
const char* ToString(int index, std::size_t* length = nullptr) const;
|
||||
void* ToUserdata(int index) const;
|
||||
void* ToUserdata(int index, const char* tname) const;
|
||||
void* ToUserdata(int index, const NzString& tname) const;
|
||||
void Remove(int index);
|
||||
void Replace(int index);
|
||||
|
||||
NzLuaInstance& operator=(const NzLuaInstance&) = delete;
|
||||
NzLuaInstance& operator=(NzLuaInstance&&) = delete; ///TODO
|
||||
void SetField(const char* name, int index = -2);
|
||||
void SetField(const String& name, int index = -2);
|
||||
void SetGlobal(const char* name);
|
||||
void SetGlobal(const String& name);
|
||||
void SetMetatable(const char* tname);
|
||||
void SetMetatable(const String& tname);
|
||||
void SetMetatable(int index);
|
||||
void SetMemoryLimit(UInt32 memoryLimit);
|
||||
void SetTable(int index = -3);
|
||||
void SetTimeLimit(UInt32 timeLimit);
|
||||
|
||||
static int GetIndexOfUpValue(int upValue);
|
||||
static NzLuaInstance* GetInstance(lua_State* state);
|
||||
bool ToBoolean(int index) const;
|
||||
long long ToInteger(int index, bool* succeeded = nullptr) const;
|
||||
double ToNumber(int index, bool* succeeded = nullptr) const;
|
||||
const void* ToPointer(int index) const;
|
||||
const char* ToString(int index, std::size_t* length = nullptr) const;
|
||||
void* ToUserdata(int index) const;
|
||||
void* ToUserdata(int index, const char* tname) const;
|
||||
void* ToUserdata(int index, const String& tname) const;
|
||||
|
||||
private:
|
||||
bool Run(int argCount, int resultCount);
|
||||
LuaInstance& operator=(const LuaInstance&) = delete;
|
||||
LuaInstance& operator=(LuaInstance&&) = delete; ///TODO
|
||||
|
||||
static void* MemoryAllocator(void *ud, void *ptr, std::size_t osize, std::size_t nsize);
|
||||
static int ProxyFunc(lua_State* state);
|
||||
static void TimeLimiter(lua_State* state, lua_Debug* debug);
|
||||
static int GetIndexOfUpValue(int upValue);
|
||||
static LuaInstance* GetInstance(lua_State* state);
|
||||
|
||||
nzUInt32 m_memoryLimit;
|
||||
nzUInt32 m_memoryUsage;
|
||||
nzUInt32 m_timeLimit;
|
||||
NzClock m_clock;
|
||||
NzString m_lastError;
|
||||
lua_State* m_state;
|
||||
unsigned int m_level;
|
||||
};
|
||||
private:
|
||||
bool Run(int argCount, int resultCount);
|
||||
|
||||
static void* MemoryAllocator(void *ud, void *ptr, std::size_t osize, std::size_t nsize);
|
||||
static int ProxyFunc(lua_State* state);
|
||||
static void TimeLimiter(lua_State* state, lua_Debug* debug);
|
||||
|
||||
UInt32 m_memoryLimit;
|
||||
UInt32 m_memoryUsage;
|
||||
UInt32 m_timeLimit;
|
||||
Clock m_clock;
|
||||
String m_lastError;
|
||||
lua_State* m_state;
|
||||
unsigned int m_level;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Lua/LuaInstance.inl>
|
||||
|
||||
|
||||
@@ -5,163 +5,166 @@
|
||||
#include <Nazara/Core/Algorithm.hpp>
|
||||
#include <string>
|
||||
|
||||
// Functions args
|
||||
bool NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<bool>)
|
||||
namespace Nz
|
||||
{
|
||||
return instance.CheckBoolean(index);
|
||||
}
|
||||
|
||||
double NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<double>)
|
||||
{
|
||||
return instance.CheckNumber(index);
|
||||
}
|
||||
|
||||
float NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<float>)
|
||||
{
|
||||
return static_cast<float>(instance.CheckNumber(index));
|
||||
}
|
||||
|
||||
int NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<int>)
|
||||
{
|
||||
return static_cast<int>(instance.CheckInteger(index));
|
||||
}
|
||||
|
||||
std::string NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<std::string>)
|
||||
{
|
||||
std::size_t strLength = 0;
|
||||
const char* str = instance.CheckString(index, &strLength);
|
||||
|
||||
return std::string(str, strLength);
|
||||
}
|
||||
|
||||
NzString NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<NzString>)
|
||||
{
|
||||
std::size_t strLength = 0;
|
||||
const char* str = instance.CheckString(index, &strLength);
|
||||
|
||||
return NzString(str, strLength);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<const T&>)
|
||||
{
|
||||
return NzLuaImplQueryArg(instance, index, NzTypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_unsigned<T>::value, T> NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<T>)
|
||||
{
|
||||
return static_cast<T>(NzLuaImplQueryArg(instance, index, NzTypeTag<typename std::make_signed<T>::type>()));
|
||||
}
|
||||
|
||||
// Function returns
|
||||
int NzLuaImplReplyVal(NzLuaInstance& instance, bool&& val, NzTypeTag<bool>)
|
||||
{
|
||||
instance.PushBoolean(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NzLuaImplReplyVal(NzLuaInstance& instance, double&& val, NzTypeTag<double>)
|
||||
{
|
||||
instance.PushNumber(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NzLuaImplReplyVal(NzLuaInstance& instance, float&& val, NzTypeTag<float>)
|
||||
{
|
||||
instance.PushNumber(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NzLuaImplReplyVal(NzLuaInstance& instance, int&& val, NzTypeTag<int>)
|
||||
{
|
||||
instance.PushInteger(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NzLuaImplReplyVal(NzLuaInstance& instance, std::string&& val, NzTypeTag<std::string>)
|
||||
{
|
||||
instance.PushString(val.c_str(), val.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NzLuaImplReplyVal(NzLuaInstance& instance, NzString&& val, NzTypeTag<NzString>)
|
||||
{
|
||||
instance.PushString(std::move(val));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
int NzLuaImplReplyVal(NzLuaInstance& instance, std::pair<T1, T2>&& val, NzTypeTag<std::pair<T1, T2>>)
|
||||
{
|
||||
int retVal = 0;
|
||||
|
||||
retVal += NzLuaImplReplyVal(instance, std::move(val.first), NzTypeTag<T1>());
|
||||
retVal += NzLuaImplReplyVal(instance, std::move(val.second), NzTypeTag<T2>());
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_unsigned<T>::value, int> NzLuaImplReplyVal(NzLuaInstance& instance, T&& val, NzTypeTag<T>)
|
||||
{
|
||||
using SignedT = typename std::make_signed<T>::type;
|
||||
|
||||
return NzLuaImplReplyVal(instance, val, NzTypeTag<SignedT>());
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
class NzLuaImplFunctionProxy
|
||||
{
|
||||
public:
|
||||
NzLuaImplFunctionProxy(NzLuaInstance& instance) :
|
||||
m_instance(instance)
|
||||
{
|
||||
}
|
||||
|
||||
template<unsigned int N, typename ArgType>
|
||||
void ProcessArgs()
|
||||
{
|
||||
std::get<N>(m_args) = std::move(NzLuaImplQueryArg(m_instance, N+1, NzTypeTag<ArgType>()));
|
||||
}
|
||||
|
||||
template<int N, typename ArgType1, typename ArgType2, typename... Rest>
|
||||
void ProcessArgs()
|
||||
{
|
||||
ProcessArgs<N, ArgType1>();
|
||||
ProcessArgs<N+1, ArgType2, Rest...>();
|
||||
}
|
||||
|
||||
void ProcessArgs()
|
||||
{
|
||||
ProcessArgs<0, Args...>();
|
||||
}
|
||||
|
||||
int Invoke(void (*func)(Args...))
|
||||
{
|
||||
NzApply(func, m_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename Ret>
|
||||
int Invoke(Ret (*func)(Args...))
|
||||
{
|
||||
return NzLuaImplReplyVal(m_instance, std::move(NzApply(func, m_args)), NzTypeTag<decltype(NzApply(func, m_args))>());
|
||||
}
|
||||
|
||||
private:
|
||||
NzLuaInstance& m_instance;
|
||||
std::tuple<Args...> m_args;
|
||||
};
|
||||
|
||||
template<typename R, typename... Args>
|
||||
void NzLuaInstance::PushFunction(R(*func)(Args...))
|
||||
{
|
||||
PushFunction([func](NzLuaInstance& instance) -> int
|
||||
// Functions args
|
||||
bool LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<bool>)
|
||||
{
|
||||
NzLuaImplFunctionProxy<Args...> handler(instance);
|
||||
handler.ProcessArgs();
|
||||
return instance.CheckBoolean(index);
|
||||
}
|
||||
|
||||
return handler.Invoke(func);
|
||||
});
|
||||
double LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<double>)
|
||||
{
|
||||
return instance.CheckNumber(index);
|
||||
}
|
||||
|
||||
float LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<float>)
|
||||
{
|
||||
return static_cast<float>(instance.CheckNumber(index));
|
||||
}
|
||||
|
||||
int LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<int>)
|
||||
{
|
||||
return static_cast<int>(instance.CheckInteger(index));
|
||||
}
|
||||
|
||||
std::string LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<std::string>)
|
||||
{
|
||||
std::size_t strLength = 0;
|
||||
const char* str = instance.CheckString(index, &strLength);
|
||||
|
||||
return std::string(str, strLength);
|
||||
}
|
||||
|
||||
String LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<String>)
|
||||
{
|
||||
std::size_t strLength = 0;
|
||||
const char* str = instance.CheckString(index, &strLength);
|
||||
|
||||
return String(str, strLength);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<const T&>)
|
||||
{
|
||||
return LuaImplQueryArg(instance, index, TypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_unsigned<T>::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<T>)
|
||||
{
|
||||
return static_cast<T>(LuaImplQueryArg(instance, index, TypeTag<typename std::make_signed<T>::type>()));
|
||||
}
|
||||
|
||||
// Function returns
|
||||
int LuaImplReplyVal(LuaInstance& instance, bool&& val, TypeTag<bool>)
|
||||
{
|
||||
instance.PushBoolean(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaImplReplyVal(LuaInstance& instance, double&& val, TypeTag<double>)
|
||||
{
|
||||
instance.PushNumber(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaImplReplyVal(LuaInstance& instance, float&& val, TypeTag<float>)
|
||||
{
|
||||
instance.PushNumber(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaImplReplyVal(LuaInstance& instance, int&& val, TypeTag<int>)
|
||||
{
|
||||
instance.PushInteger(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaImplReplyVal(LuaInstance& instance, std::string&& val, TypeTag<std::string>)
|
||||
{
|
||||
instance.PushString(val.c_str(), val.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaImplReplyVal(LuaInstance& instance, String&& val, TypeTag<String>)
|
||||
{
|
||||
instance.PushString(std::move(val));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
int LuaImplReplyVal(LuaInstance& instance, std::pair<T1, T2>&& val, TypeTag<std::pair<T1, T2>>)
|
||||
{
|
||||
int retVal = 0;
|
||||
|
||||
retVal += LuaImplReplyVal(instance, std::move(val.first), TypeTag<T1>());
|
||||
retVal += LuaImplReplyVal(instance, std::move(val.second), TypeTag<T2>());
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_unsigned<T>::value, int> LuaImplReplyVal(LuaInstance& instance, T&& val, TypeTag<T>)
|
||||
{
|
||||
using SignedT = typename std::make_signed<T>::type;
|
||||
|
||||
return LuaImplReplyVal(instance, val, TypeTag<SignedT>());
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
class LuaImplFunctionProxy
|
||||
{
|
||||
public:
|
||||
LuaImplFunctionProxy(LuaInstance& instance) :
|
||||
m_instance(instance)
|
||||
{
|
||||
}
|
||||
|
||||
template<unsigned int N, typename ArgType>
|
||||
void ProcessArgs()
|
||||
{
|
||||
std::get<N>(m_args) = std::move(LuaImplQueryArg(m_instance, N+1, TypeTag<ArgType>()));
|
||||
}
|
||||
|
||||
template<int N, typename ArgType1, typename ArgType2, typename... Rest>
|
||||
void ProcessArgs()
|
||||
{
|
||||
ProcessArgs<N, ArgType1>();
|
||||
ProcessArgs<N+1, ArgType2, Rest...>();
|
||||
}
|
||||
|
||||
void ProcessArgs()
|
||||
{
|
||||
ProcessArgs<0, Args...>();
|
||||
}
|
||||
|
||||
int Invoke(void (*func)(Args...))
|
||||
{
|
||||
Apply(func, m_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename Ret>
|
||||
int Invoke(Ret (*func)(Args...))
|
||||
{
|
||||
return LuaImplReplyVal(m_instance, std::move(Apply(func, m_args)), TypeTag<decltype(Apply(func, m_args))>());
|
||||
}
|
||||
|
||||
private:
|
||||
LuaInstance& m_instance;
|
||||
std::tuple<Args...> m_args;
|
||||
};
|
||||
|
||||
template<typename R, typename... Args>
|
||||
void LuaInstance::PushFunction(R(*func)(Args...))
|
||||
{
|
||||
PushFunction([func](LuaInstance& instance) -> int
|
||||
{
|
||||
LuaImplFunctionProxy<Args...> handler(instance);
|
||||
handler.ProcessArgs();
|
||||
|
||||
return handler.Invoke(func);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user