Browse Source

LUA binding. Some additions

Panagiotis Christopoulos Charitos 11 years ago
parent
commit
ba8fafbe22

+ 72 - 38
include/anki/script/LuaBinder.h

@@ -18,33 +18,52 @@
 
 namespace anki {
 
+/// LUA userdata
+class UserData
+{
+public:
+	I64 m_sig = 0; ///< Signature to identify the user data.
+	void* m_data = nullptr;
+	Bool8 m_gc = false; ///< Garbage collection on?
+};
+
 /// Lua binder class. A wrapper on top of LUA
 class LuaBinder
 {
 public:
 	template<typename T>
-	using Allocator = HeapAllocator<T>;
+	using Allocator = ChainAllocator<T>;
 
-	LuaBinder(Allocator<U8>& alloc, void* parent);
+	LuaBinder();
 	~LuaBinder();
 
-	/// @privatesection
-	/// {
-	lua_State* _getLuaState()
+	ANKI_USE_RESULT Error create(Allocator<U8>& alloc, void* parent);
+
+	lua_State* getLuaState()
 	{
 		return m_l;
 	}
 
-	Allocator<U8> _getAllocator() const
+	Allocator<U8> getAllocator() const
 	{
 		return m_alloc;
 	}
 
-	void* _getParent() const
+	void* getParent() const
 	{
 		return m_parent;
 	}
 
+	/// Expose a variable to the lua state
+	template<typename T>
+	void exposeVariable(const char* name, T* y);
+
+	/// Evaluate a string
+	ANKI_USE_RESULT Error evalString(const CString& str);
+
+	/// For debugging purposes
+	static void stackDump(lua_State* l);
+
 	/// Make sure that the arguments match the argsCount number
 	static void checkArgsCount(lua_State* l, I argsCount);
 
@@ -55,41 +74,37 @@ public:
 	static void pushLuaCFuncMethod(lua_State* l, const char* name,
 		lua_CFunction luafunc);
 
-	/// Add a new static function in the class
+	/// Add a new static function in the class.
 	static void pushLuaCFuncStaticMethod(lua_State* l, const char* className,
 		const char* name, lua_CFunction luafunc);
 
+	/// Get a number from the stack.
 	template<typename TNumber>
 	static ANKI_USE_RESULT Error checkNumber(
-		lua_State* l, I stackIdx, TNumber& number)
-	{
-		lua_Number lnum;
-		Error err = checkNumberInternal(l, stackIdx, lnum);
-		if(!err)
-		{
-			number = lnum;
-		}
-
-		return err;
-	}
+		lua_State* l, I stackIdx, TNumber& number);
 
-	static void* luaAlloc(lua_State* l, size_t size);
+	/// Get a string from the stack.
+	static ANKI_USE_RESULT Error checkString(
+		lua_State* l, I32 stackIdx, const char*& out);
 
-	static void luaFree(lua_State* l, void* ptr);
-	/// }
+	/// Get some user data from the stack.
+	/// The function uses the type signature to validate the type and not the 
+	/// typeName. That is supposed to be faster.
+	static ANKI_USE_RESULT Error checkUserData(
+		lua_State* l, I32 stackIdx, const char* typeName, I64 typeSignature, 
+		UserData*& out);
 
-	/// Expose a variable to the lua state
-	template<typename T>
-	void exposeVariable(const char* name, T* y);
+	/// Allocate memory.
+	static void* luaAlloc(lua_State* l, size_t size);
 
-	/// Evaluate a file
-	void evalFile(const CString& filename);
+	/// Free memory.
+	static void luaFree(lua_State* l, void* ptr);
 
-	/// Evaluate a string
-	void evalString(const CString& str);
+	template<typename TWrapedType>
+	static I64 getWrappedTypeSignature();
 
-	/// For debugging purposes
-	static void stackDump(lua_State* l);
+	template<typename TWrapedType>
+	static const char* getWrappedTypeName();
 
 private:
 	Allocator<U8> m_alloc;
@@ -100,17 +115,36 @@ private:
 		void* userData, void* ptr, PtrSize osize, PtrSize nsize);
 
 	static ANKI_USE_RESULT Error checkNumberInternal(
-		lua_State* l, I stackIdx, lua_Number& number);
+		lua_State* l, I32 stackIdx, lua_Number& number);
 };
 
 //==============================================================================
-/// lua userdata
-class UserData
+template<typename TNumber>
+inline Error LuaBinder::checkNumber(
+	lua_State* l, I stackIdx, TNumber& number)
 {
-public:
-	void* m_data = nullptr;
-	Bool8 m_gc = false; ///< Garbage collection on?
-};
+	lua_Number lnum;
+	Error err = checkNumberInternal(l, stackIdx, lnum);
+	if(!err)
+	{
+		number = lnum;
+	}
+
+	return err;
+}
+
+//==============================================================================
+template<typename T>
+inline void LuaBinder::exposeVariable(const char* name, T* y)
+{
+	void* ptr = lua_newuserdata(m_l, sizeof(UserData));
+	UserData* ud = reinterpret_cast<UserData*>(ptr);
+	ud->m_data = y;
+	ud->m_gc = false;
+	ud->m_sig = getWrappedTypeSignature<T>();
+	luaL_setmetatable(m_l, getWrappedTypeName<T>());
+	lua_setglobal(m_l, name);
+}
 
 } // end namespace anki
 

+ 10 - 3
include/anki/script/ScriptManager.h

@@ -17,13 +17,18 @@ class SceneGraph;
 /// @{
 
 /// The scripting manager
-class ScriptManager: public LuaBinder
+class ScriptManager
 {
 public:
-	ScriptManager(HeapAllocator<U8>& alloc, SceneGraph* scene);
-
+	ScriptManager();
 	~ScriptManager();
 
+	/// Create the script manager.
+	ANKI_USE_RESULT Error create(
+		AllocAlignedCallback allocCb, 
+		void* allocCbData,
+		SceneGraph* scene);
+
 	/// @privatesection
 	/// @{
 	SceneGraph& _getSceneGraph()
@@ -34,6 +39,8 @@ public:
 
 public:
 	SceneGraph* m_scene = nullptr;
+	ChainAllocator<U8> m_alloc;
+	LuaBinder m_lua;
 };
 
 /// @}

+ 3 - 0
include/anki/util/Memory.h

@@ -277,6 +277,9 @@ public:
 	/// Get the number of users for this pool
 	U32 getUsersCount() const;
 
+	/// Return number of allocations
+	U32 getAllocationsCount() const;
+
 	/// @name Methods used for optimizing future chains
 	/// @{
 	PtrSize getChunksCount() const;

+ 85 - 15
src/script/LuaBinder.cpp

@@ -14,23 +14,13 @@ namespace anki {
 //==============================================================================
 static int luaPanic(lua_State* l)
 {
-	std::string err(lua_tostring(l, -1));
-	ANKI_LOGE("Lua panic attack: %s", err.c_str());
+	ANKI_LOGE("Lua panic attack: %s", lua_tostring(l, -1));
 	abort();
 }
 
 //==============================================================================
-LuaBinder::LuaBinder(Allocator<U8>& alloc, void* parent)
-:	m_parent(parent)
-{
-	m_alloc = alloc;
-
-	m_l = lua_newstate(luaAllocCallback, this);
-	//m_l = luaL_newstate();
-	luaL_openlibs(m_l);
-	lua_atpanic(m_l, &luaPanic);
-	lua_setuserdata(m_l, this);
-}
+LuaBinder::LuaBinder()
+{}
 
 //==============================================================================
 LuaBinder::~LuaBinder()
@@ -41,6 +31,20 @@ LuaBinder::~LuaBinder()
 		&& "Leaking memory");
 }
 
+//==============================================================================
+Error LuaBinder::create(Allocator<U8>& alloc, void* parent)
+{
+	m_parent = parent;
+	m_alloc = alloc;
+
+	m_l = lua_newstate(luaAllocCallback, this);
+	luaL_openlibs(m_l);
+	lua_atpanic(m_l, &luaPanic);
+	lua_setuserdata(m_l, this);
+
+	return ErrorCode::NONE;
+}
+
 //==============================================================================
 void* LuaBinder::luaAllocCallback(
 	void* userData, void* ptr, PtrSize osize, PtrSize nsize)
@@ -83,14 +87,20 @@ void* LuaBinder::luaAllocCallback(
 }
 
 //==============================================================================
-void LuaBinder::evalString(const CString& str)
+Error LuaBinder::evalString(const CString& str)
 {
+	Error err = ErrorCode::NONE;
 	int e = luaL_dostring(m_l, &str[0]);
 	if(e)
 	{
 		ANKI_LOGE("%s", lua_tostring(m_l, -1));
 		lua_pop(m_l, 1);
+		err = ErrorCode::USER_DATA;
 	}
+
+	lua_gc(m_l, LUA_GCCOLLECT, 0);
+
+	return err;
 }
 
 //==============================================================================
@@ -138,7 +148,7 @@ void LuaBinder::pushLuaCFuncStaticMethod(lua_State* l, const char* className,
 
 //==============================================================================
 Error LuaBinder::checkNumberInternal(
-	lua_State* l, I stackIdx, lua_Number& number)
+	lua_State* l, I32 stackIdx, lua_Number& number)
 {
 	Error err = ErrorCode::NONE;
 	lua_Number lnum;
@@ -159,6 +169,66 @@ Error LuaBinder::checkNumberInternal(
 	return err;
 }
 
+//==============================================================================
+Error LuaBinder::checkString(lua_State* l, I32 stackIdx, const char*& out)
+{
+	Error err = ErrorCode::NONE;
+	const char* s = lua_tolstring(l, stackIdx, nullptr);
+	if(s != nullptr)
+	{
+		out = s;
+	}
+	else
+	{
+		err = ErrorCode::USER_DATA;
+		lua_pushfstring(
+			l, "String expected. Got %s", luaL_typename(l, stackIdx));
+	}
+
+	return err;
+}
+
+//==============================================================================
+Error LuaBinder::checkUserData(
+	lua_State* l, I32 stackIdx, const char* typeName, I64 typeSignature,
+	UserData*& out)
+{
+	Error err = ErrorCode::NONE;
+
+	void* p = lua_touserdata(l, stackIdx);
+	if(p != nullptr)
+	{
+		out = reinterpret_cast<UserData*>(p);
+		if(out->m_sig == typeSignature)
+		{
+			// All done!
+			ANKI_ASSERT(out->m_data);
+
+			// Check using a LUA method again
+			ANKI_ASSERT(luaL_testudata(l, stackIdx, typeName) != nullptr
+				&& "ANKI type check passes but LUA's type check failed");
+		}
+		else
+		{
+			// It's not the correct user data
+			err = ErrorCode::USER_DATA;
+		}
+	}
+	else
+	{
+		// It's not user data
+		err = ErrorCode::USER_DATA;
+	}
+
+	if(err)
+	{
+		lua_pushfstring(l, "Userdata of %s expected. Got %s", 
+			typeName, luaL_typename(l, stackIdx));
+	}
+
+	return err;
+}
+
 //==============================================================================
 void* LuaBinder::luaAlloc(lua_State* l, size_t size)
 {

File diff suppressed because it is too large
+ 128 - 224
src/script/Math.cpp


+ 14 - 8
src/script/Renderer.cpp

@@ -17,6 +17,18 @@ namespace anki {
 //==============================================================================
 static const char* classnameDbg = "Dbg";
 
+template<>
+I64 LuaBinder::getWrappedTypeSignature<Dbg>()
+{
+	return -2784798555522127122;
+}
+
+template<>
+const char* LuaBinder::getWrappedTypeName<Dbg>()
+{
+	return classnameDbg;
+}
+
 //==============================================================================
 /// Pre-wrap method Dbg::getEnabled.
 static inline int pwrapDbggetEnabled(lua_State* l)
@@ -25,14 +37,11 @@ static inline int pwrapDbggetEnabled(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 1);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameDbg);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameDbg, -2784798555522127122, ud)) return -1;
 	Dbg* self = reinterpret_cast<Dbg*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
@@ -63,14 +72,11 @@ static inline int pwrapDbgsetEnabled(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 2);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameDbg);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameDbg, -2784798555522127122, ud)) return -1;
 	Dbg* self = reinterpret_cast<Dbg*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	

+ 89 - 64
src/script/Scene.cpp

@@ -36,6 +36,18 @@ static T* newSceneNode(SceneGraph* scene, CString name, TArgs... args)
 //==============================================================================
 static const char* classnameMoveComponent = "MoveComponent";
 
+template<>
+I64 LuaBinder::getWrappedTypeSignature<MoveComponent>()
+{
+	return 2038493110845313445;
+}
+
+template<>
+const char* LuaBinder::getWrappedTypeName<MoveComponent>()
+{
+	return classnameMoveComponent;
+}
+
 //==============================================================================
 /// Pre-wrap method MoveComponent::setLocalOrigin.
 static inline int pwrapMoveComponentsetLocalOrigin(lua_State* l)
@@ -44,22 +56,17 @@ static inline int pwrapMoveComponentsetLocalOrigin(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 2);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameMoveComponent);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameMoveComponent, 2038493110845313445, ud)) return -1;
 	MoveComponent* self = reinterpret_cast<MoveComponent*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
 	// Pop arguments
-	voidp = luaL_checkudata(l, 2, "Vec4");
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 2, "Vec4", 6804478823655046386, ud)) return -1;
 	Vec4* iarg0 = reinterpret_cast<Vec4*>(ud->m_data);
-	ANKI_ASSERT(iarg0 != nullptr);
 	const Vec4& arg0(*iarg0);
 	
 	// Call the method
@@ -86,14 +93,11 @@ static inline int pwrapMoveComponentgetLocalOrigin(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 1);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameMoveComponent);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameMoveComponent, 2038493110845313445, ud)) return -1;
 	MoveComponent* self = reinterpret_cast<MoveComponent*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
@@ -106,6 +110,7 @@ static inline int pwrapMoveComponentgetLocalOrigin(lua_State* l)
 	luaL_setmetatable(l, "Vec4");
 	ud->m_data = const_cast<void*>(reinterpret_cast<const void*>(&ret));
 	ud->m_gc = false;
+	ud->m_sig = 6804478823655046386;
 	
 	return 1;
 }
@@ -128,22 +133,17 @@ static inline int pwrapMoveComponentsetLocalRotation(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 2);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameMoveComponent);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameMoveComponent, 2038493110845313445, ud)) return -1;
 	MoveComponent* self = reinterpret_cast<MoveComponent*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
 	// Pop arguments
-	voidp = luaL_checkudata(l, 2, "Mat3x4");
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 2, "Mat3x4", -2654194732934255869, ud)) return -1;
 	Mat3x4* iarg0 = reinterpret_cast<Mat3x4*>(ud->m_data);
-	ANKI_ASSERT(iarg0 != nullptr);
 	const Mat3x4& arg0(*iarg0);
 	
 	// Call the method
@@ -170,14 +170,11 @@ static inline int pwrapMoveComponentgetLocalRotation(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 1);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameMoveComponent);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameMoveComponent, 2038493110845313445, ud)) return -1;
 	MoveComponent* self = reinterpret_cast<MoveComponent*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
@@ -190,6 +187,7 @@ static inline int pwrapMoveComponentgetLocalRotation(lua_State* l)
 	luaL_setmetatable(l, "Mat3x4");
 	ud->m_data = const_cast<void*>(reinterpret_cast<const void*>(&ret));
 	ud->m_gc = false;
+	ud->m_sig = -2654194732934255869;
 	
 	return 1;
 }
@@ -212,14 +210,11 @@ static inline int pwrapMoveComponentsetLocalScale(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 2);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameMoveComponent);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameMoveComponent, 2038493110845313445, ud)) return -1;
 	MoveComponent* self = reinterpret_cast<MoveComponent*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
@@ -251,14 +246,11 @@ static inline int pwrapMoveComponentgetLocalScale(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 1);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameMoveComponent);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameMoveComponent, 2038493110845313445, ud)) return -1;
 	MoveComponent* self = reinterpret_cast<MoveComponent*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
@@ -302,6 +294,18 @@ static inline void wrapMoveComponent(lua_State* l)
 //==============================================================================
 static const char* classnameSceneNode = "SceneNode";
 
+template<>
+I64 LuaBinder::getWrappedTypeSignature<SceneNode>()
+{
+	return -2220074417980276571;
+}
+
+template<>
+const char* LuaBinder::getWrappedTypeName<SceneNode>()
+{
+	return classnameSceneNode;
+}
+
 //==============================================================================
 /// Pre-wrap method SceneNode::getName.
 static inline int pwrapSceneNodegetName(lua_State* l)
@@ -310,14 +314,11 @@ static inline int pwrapSceneNodegetName(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 1);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameSceneNode);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameSceneNode, -2220074417980276571, ud)) return -1;
 	SceneNode* self = reinterpret_cast<SceneNode*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
@@ -348,22 +349,17 @@ static inline int pwrapSceneNodeaddChild(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 2);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameSceneNode);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameSceneNode, -2220074417980276571, ud)) return -1;
 	SceneNode* self = reinterpret_cast<SceneNode*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
 	// Pop arguments
-	voidp = luaL_checkudata(l, 2, "SceneNode");
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 2, "SceneNode", -2220074417980276571, ud)) return -1;
 	SceneNode* iarg0 = reinterpret_cast<SceneNode*>(ud->m_data);
-	ANKI_ASSERT(iarg0 != nullptr);
 	SceneNode* arg0(iarg0);
 	
 	// Call the method
@@ -399,14 +395,11 @@ static inline int pwrapSceneNodegetMoveComponent(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 1);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameSceneNode);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameSceneNode, -2220074417980276571, ud)) return -1;
 	SceneNode* self = reinterpret_cast<SceneNode*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
@@ -425,6 +418,7 @@ static inline int pwrapSceneNodegetMoveComponent(lua_State* l)
 	luaL_setmetatable(l, "MoveComponent");
 	ud->m_data = reinterpret_cast<void*>(ret);
 	ud->m_gc = false;
+	ud->m_sig = 2038493110845313445;
 	
 	return 1;
 }
@@ -457,6 +451,18 @@ static inline void wrapSceneNode(lua_State* l)
 //==============================================================================
 static const char* classnameModelNode = "ModelNode";
 
+template<>
+I64 LuaBinder::getWrappedTypeSignature<ModelNode>()
+{
+	return -1856316251880904290;
+}
+
+template<>
+const char* LuaBinder::getWrappedTypeName<ModelNode>()
+{
+	return classnameModelNode;
+}
+
 //==============================================================================
 /// Pre-wrap method ModelNode::getSceneNodeBase.
 static inline int pwrapModelNodegetSceneNodeBase(lua_State* l)
@@ -465,14 +471,11 @@ static inline int pwrapModelNodegetSceneNodeBase(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 1);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameModelNode);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameModelNode, -1856316251880904290, ud)) return -1;
 	ModelNode* self = reinterpret_cast<ModelNode*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
@@ -485,6 +488,7 @@ static inline int pwrapModelNodegetSceneNodeBase(lua_State* l)
 	luaL_setmetatable(l, "SceneNode");
 	ud->m_data = reinterpret_cast<void*>(&ret);
 	ud->m_gc = false;
+	ud->m_sig = -2220074417980276571;
 	
 	return 1;
 }
@@ -515,6 +519,18 @@ static inline void wrapModelNode(lua_State* l)
 //==============================================================================
 static const char* classnameInstanceNode = "InstanceNode";
 
+template<>
+I64 LuaBinder::getWrappedTypeSignature<InstanceNode>()
+{
+	return -2063375830923741403;
+}
+
+template<>
+const char* LuaBinder::getWrappedTypeName<InstanceNode>()
+{
+	return classnameInstanceNode;
+}
+
 //==============================================================================
 /// Pre-wrap method InstanceNode::getSceneNodeBase.
 static inline int pwrapInstanceNodegetSceneNodeBase(lua_State* l)
@@ -523,14 +539,11 @@ static inline int pwrapInstanceNodegetSceneNodeBase(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 1);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameInstanceNode);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameInstanceNode, -2063375830923741403, ud)) return -1;
 	InstanceNode* self = reinterpret_cast<InstanceNode*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
@@ -543,6 +556,7 @@ static inline int pwrapInstanceNodegetSceneNodeBase(lua_State* l)
 	luaL_setmetatable(l, "SceneNode");
 	ud->m_data = reinterpret_cast<void*>(&ret);
 	ud->m_gc = false;
+	ud->m_sig = -2220074417980276571;
 	
 	return 1;
 }
@@ -573,6 +587,18 @@ static inline void wrapInstanceNode(lua_State* l)
 //==============================================================================
 static const char* classnameSceneGraph = "SceneGraph";
 
+template<>
+I64 LuaBinder::getWrappedTypeSignature<SceneGraph>()
+{
+	return -7754439619132389154;
+}
+
+template<>
+const char* LuaBinder::getWrappedTypeName<SceneGraph>()
+{
+	return classnameSceneGraph;
+}
+
 //==============================================================================
 /// Pre-wrap method SceneGraph::newModelNode.
 static inline int pwrapSceneGraphnewModelNode(lua_State* l)
@@ -581,21 +607,20 @@ static inline int pwrapSceneGraphnewModelNode(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 3);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameSceneGraph);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameSceneGraph, -7754439619132389154, ud)) return -1;
 	SceneGraph* self = reinterpret_cast<SceneGraph*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
 	// Pop arguments
-	const char* arg0(luaL_checkstring(l, 2));
+	const char* arg0;
+	if(LuaBinder::checkString(l, 2, arg0)) return -1;
 	
-	const char* arg1(luaL_checkstring(l, 3));
+	const char* arg1;
+	if(LuaBinder::checkString(l, 3, arg1)) return -1;
 	
 	// Call the method
 	ModelNode* ret = newSceneNode<ModelNode>(self, arg0, arg1);
@@ -612,6 +637,7 @@ static inline int pwrapSceneGraphnewModelNode(lua_State* l)
 	luaL_setmetatable(l, "ModelNode");
 	ud->m_data = reinterpret_cast<void*>(ret);
 	ud->m_gc = false;
+	ud->m_sig = -1856316251880904290;
 	
 	return 1;
 }
@@ -634,19 +660,17 @@ static inline int pwrapSceneGraphnewInstanceNode(lua_State* l)
 	(void)ud;
 	void* voidp;
 	(void)voidp;
-	Error err = ErrorCode::NONE;
-	(void)err;
 	
 	LuaBinder::checkArgsCount(l, 2);
 	
 	// Get "this" as "self"
-	voidp = luaL_checkudata(l, 1, classnameSceneGraph);
-	ud = reinterpret_cast<UserData*>(voidp);
+	if(LuaBinder::checkUserData(l, 1, classnameSceneGraph, -7754439619132389154, ud)) return -1;
 	SceneGraph* self = reinterpret_cast<SceneGraph*>(ud->m_data);
 	ANKI_ASSERT(self != nullptr);
 	
 	// Pop arguments
-	const char* arg0(luaL_checkstring(l, 2));
+	const char* arg0;
+	if(LuaBinder::checkString(l, 2, arg0)) return -1;
 	
 	// Call the method
 	InstanceNode* ret = newSceneNode<InstanceNode>(self, arg0);
@@ -663,6 +687,7 @@ static inline int pwrapSceneGraphnewInstanceNode(lua_State* l)
 	luaL_setmetatable(l, "InstanceNode");
 	ud->m_data = reinterpret_cast<void*>(ret);
 	ud->m_gc = false;
+	ud->m_sig = -2063375830923741403;
 	
 	return 1;
 }

+ 21 - 11
src/script/ScriptManager.cpp

@@ -69,15 +69,30 @@ ANKI_SCRIPT_WRAP(Anki)
 	wrap##x(l);
 
 //==============================================================================
-ScriptManager::ScriptManager(HeapAllocator<U8>& alloc, SceneGraph* scene)
-:	LuaBinder(alloc, this),
-	m_scene(scene)
+ScriptManager::ScriptManager()
+{}
+
+//==============================================================================
+ScriptManager::~ScriptManager()
+{
+	ANKI_LOGI("Destroying scripting engine...");
+}
+
+//==============================================================================
+Error ScriptManager::create(
+	AllocAlignedCallback allocCb, 
+	void* allocCbData, SceneGraph* scene)
 {
 	ANKI_LOGI("Initializing scripting engine...");
 
-	lua_State* l = _getLuaState();
+	m_scene = scene;
+	m_alloc = ChainAllocator<U8>(allocCb, allocCbData, 1024, 1024);
 
-	// Global functions
+	Error err = m_lua.create(m_alloc, this);
+	if(err) return err;
+
+	// Wrap stuff
+	lua_State* l = m_lua.getLuaState();
 #if 0
 	ANKI_SCRIPT_CALL_WRAP(Anki);
 #endif
@@ -87,12 +102,7 @@ ScriptManager::ScriptManager(HeapAllocator<U8>& alloc, SceneGraph* scene)
 	ANKI_SCRIPT_CALL_WRAP(Scene);
 
 	ANKI_LOGI("Scripting engine initialized");
-}
-
-//==============================================================================
-ScriptManager::~ScriptManager()
-{
-	ANKI_LOGI("Destroying scripting engine...");
+	return err;
 }
 
 } // end namespace anki

+ 37 - 20
src/script/lua_glue_gen.py

@@ -28,6 +28,10 @@ def parse_commandline():
 
 	return options.inp.split(":")
 
+def type_sig(value):
+	""" Calculate the signature of a type """
+	return hash(value)
+
 def get_base_fname(path):
 	""" From path/to/a/file.ext return the "file" """
 	return os.path.splitext(os.path.basename(path))[0]
@@ -160,6 +164,7 @@ def ret(ret_el):
 
 			wglue("::new(ud->m_data) %s(std::move(ret));" % type)
 			wglue("ud->m_gc = true;")
+		wglue("ud->m_sig = %d;" % type_sig(type))
 
 	wglue("")
 	wglue("return 1;")
@@ -170,21 +175,18 @@ def arg(arg_txt, stack_index, index):
 	(type, is_ref, is_ptr, is_const) = parse_type_decl(arg_txt)
 
 	if type_is_bool(type) or type_is_number(type):
-		#wglue("%s arg%d(luaL_checknumber(l, %d));" \
-			#% (type, index, stack_index))
 		wglue("%s arg%d;" % (type, index))
 		wglue("if(LuaBinder::checkNumber(l, %d, arg%d)) return -1;" \
 			% (stack_index, index))
 	elif type == "char" or type == "CString":
-		wglue("const char* arg%d(luaL_checkstring(l, %d));" \
-			% (index, stack_index))
+		wglue("const char* arg%d;" % index)
+		wglue("if(LuaBinder::checkString(l, %d, arg%d)) return -1;" \
+			% (stack_index, index))
 	else:
-		wglue("voidp = luaL_checkudata(l, %d, \"%s\");" \
-			% (stack_index, type))
-		wglue("ud = reinterpret_cast<UserData*>(voidp);")
+		wglue("if(LuaBinder::checkUserData(l, %d, \"%s\", %d, ud)) return -1;" \
+			% (stack_index, type, type_sig(type)))
 		wglue("%s* iarg%d = reinterpret_cast<%s*>(ud->m_data);" \
 			% (type, index, type))
-		wglue("ANKI_ASSERT(iarg%d != nullptr);" % index)
 
 		if is_ptr:
 			wglue("%s arg%d(iarg%d);" % (arg_txt, index, index))
@@ -217,6 +219,8 @@ def args(args_el, stack_index, class_name):
 	return args_str
 
 def check_args(args_el, bias):
+	""" Check number of args. Call that first because it throws error """
+
 	if args_el is None:
 		wglue("LuaBinder::checkArgsCount(l, %d);" % bias)
 	else:
@@ -267,8 +271,6 @@ def write_local_vars():
 	wglue("(void)ud;")
 	wglue("void* voidp;")
 	wglue("(void)voidp;")
-	wglue("Error err = ErrorCode::NONE;")
-	wglue("(void)err;")
 	wglue("")
 
 def method(class_name, meth_el):
@@ -291,8 +293,8 @@ def method(class_name, meth_el):
 
 	# Get this pointer
 	wglue("// Get \"this\" as \"self\"")
-	wglue("voidp = luaL_checkudata(l, %d, classname%s);" % (1, class_name))
-	wglue("ud = reinterpret_cast<UserData*>(voidp);")
+	wglue("if(LuaBinder::checkUserData(l, 1, classname%s, %d, ud)) return -1;" \
+		% (class_name, type_sig(class_name)))
 	wglue("%s* self = reinterpret_cast<%s*>(ud->m_data);" \
 		% (class_name, class_name))
 	wglue("ANKI_ASSERT(self != nullptr);")
@@ -416,12 +418,6 @@ def constructor(constr_el, class_name):
 
 	# Create new userdata
 	wglue("// Create user data")
-	wglue("voidp = lua_newuserdata(l, sizeof(UserData));")
-	wglue("ud = reinterpret_cast<UserData*>(voidp);")
-	wglue("ud->m_data = nullptr;")
-	wglue("ud->m_gc = false;")
-	wglue("luaL_setmetatable(l, classname%s);" % class_name)
-	wglue("")
 
 	wglue("void* inst = LuaBinder::luaAlloc(l, sizeof(%s));" % class_name)
 	wglue("if(ANKI_UNLIKELY(inst == nullptr))")
@@ -435,8 +431,12 @@ def constructor(constr_el, class_name):
 	wglue("::new(inst) %s(%s);" % (class_name, args_str))
 	wglue("")
 
+	wglue("voidp = lua_newuserdata(l, sizeof(UserData));")
+	wglue("ud = reinterpret_cast<UserData*>(voidp);")
 	wglue("ud->m_data = inst;")
 	wglue("ud->m_gc = true;")
+	wglue("ud->m_sig = %d;" % type_sig(class_name))
+	wglue("luaL_setmetatable(l, classname%s);" % class_name)
 	wglue("")
 
 	wglue("return 1;")
@@ -469,10 +469,11 @@ def destructor(class_name):
 	wglue("static int wrap%sDtor(lua_State* l)" % class_name)
 	wglue("{")
 	ident(1)
+	write_local_vars();
 
 	wglue("LuaBinder::checkArgsCount(l, 1);")
-	wglue("void* voidp = luaL_checkudata(l, 1, classname%s);" % class_name)
-	wglue("UserData* ud = reinterpret_cast<UserData*>(voidp);")
+	wglue("if(LuaBinder::checkUserData(l, 1, classname%s, %d, ud)) return -1;" \
+		% (class_name, type_sig(class_name)))
 
 	wglue("if(ud->m_gc)")
 	wglue("{")
@@ -510,6 +511,22 @@ def class_(class_el):
 	wglue("static const char* classname%s = \"%s\";" \
 		% (class_name, class_name))
 	wglue("")
+	wglue("template<>")
+	wglue("I64 LuaBinder::getWrappedTypeSignature<%s>()" % class_name)
+	wglue("{")
+	ident(1)
+	wglue("return %d;" % type_sig(class_name))
+	ident(-1)
+	wglue("}")
+	wglue("")
+	wglue("template<>")
+	wglue("const char* LuaBinder::getWrappedTypeName<%s>()" % class_name)
+	wglue("{")
+	ident(1)
+	wglue("return classname%s;" % class_name)
+	ident(-1)
+	wglue("}")
+	wglue("")
 
 	# Constructor declarations
 	has_constructor = False

+ 13 - 0
src/util/Memory.cpp

@@ -708,6 +708,9 @@ public:
 	/// Chunk allocation method
 	ChainMemoryPool::ChunkGrowMethod m_method;
 
+	/// Allocations number.
+	AtomicU32 m_allocationsCount;
+
 	/// Construct
 	Implementation(
 		AllocAlignedCallback allocCb, 
@@ -954,6 +957,7 @@ public:
 		{
 			mem = allocateFromChunk(ch, size, alignment);
 			ANKI_ASSERT(mem != nullptr && "The chunk should have space");
+			++m_allocationsCount;
 		}
 
 		m_lock.unlock();
@@ -1015,6 +1019,8 @@ public:
 
 		m_lock.unlock();
 
+		--m_allocationsCount;
+
 		return true;
 	}
 
@@ -1149,4 +1155,11 @@ U32 ChainMemoryPool::getUsersCount() const
 	return m_impl->m_refcount.load();
 }
 
+//==============================================================================
+U32 ChainMemoryPool::getAllocationsCount() const
+{
+	ANKI_ASSERT(m_impl != nullptr);
+	return m_impl->m_allocationsCount.load();
+}
+
 } // end namespace anki

Some files were not shown because too many files changed in this diff