; ID: 1580 ; Author: Noel - Banned ; Date: 2005-12-28 03:02:21 ; Title: Simple OO Lua Interface ; Description: An object-oriented interface to Lua SuperStrict Import Axe.Lua Private Function _lsb@ Ptr( s@ Ptr, d@ Ptr, sz% Ptr ) Local i:Int Ptr = Int Ptr(d) sz[0] = Min(i[0],32) i[0] :- sz[0] Local p@ Ptr = Byte Ptr(i[1]) i[1] :+ sz[0] Return p End Function Public Rem bbdoc: A base class for interfacing with Lua in an object-oriented manner. EndRem Type Lua Field __buffersLoaded% = 0 '' Used for DoString( ) Field _disposed% = False Field _disposable% = False Field _state@ Ptr = Null Method New( ) End Method Method Delete( ) Dispose( True ) End Method Rem bbdoc: Checks whether or not the class is usable (valid). If it isn't, it DebugLogs an exception.

It's recommended that you wrap your own calls to this in a Try/Catch construct. EndRem Method Validate( ) If ( _disposed = True ) DebugLog "Script interface is disposed" Return If ( _state = Null ) DebugLog "State is null" Return End Method Rem bbdoc: Forces the disposal of the class and/or Lua state (depending on the settings specified on creation). EndRem Method Dispose( ignoreException% = False ) If ( _disposed = True And ignoreException = False ) DebugLog "Script interface is already disposed" Return If ( _disposable = True And _state <> Null ) lua_close( _state ) EndIf _state = Null _disposed = True End Method Rem bbdoc: Resets the class properties. EndRem Method Reset( s@ Ptr, canFree% = False ) _disposed = False _state = s _disposable = canFree End Method Rem bbdoc: Creates a new Lua from an existing Lua state.

If you pass True to @canFree, the state will be freed when the class is disposed of (either on garbage collection or when the @Dispose method is called).

When extending this class, you should override this function so that it creates the extended class. That, or you can just do
New YourExtendedClass.Reset( state, True/False )
. EndRem Function FromState:Lua( s@ Ptr, canFree% = False ) Local l:Lua = New Lua l.Reset( s, canFree ) Return (l) End Function Rem bbdoc: Creates a new Lua class and Lua state. View @FromState for extra advice regarding implementation. EndRem Function Create:Lua( ) Return Lua.FromState( luaL_newstate( ), True ) End Function Rem bbdoc: Loads the lualib libraries. EndRem Method LoadLibraries( ) Validate( ) luaopen_base( _state ) luaopen_table( _state ) luaopen_string( _state ) luaopen_math( _state ) luaopen_debug( _state ) End Method Rem bbdoc: Tells the Lua state to execute a string. EndRem Method DoString( s$ ) Validate( ) Local length% = s.Length Local mem@ Ptr = s.ToCString( ) Local r:Int = lua_load( _state, _lsb, [length, Int(mem)], "__sBuffer"+__buffersLoaded ) Select ( r ) Case 1 DebugLog "Lua runtime error encountered during lua_load:~n"+PopString( ) Case 2 DebugLog "Lua file error encountered during lua_load:~n"+PopString( ) Case 3 DebugLog "Lua syntax error encountered during lua_load:~n"+PopString( ) End Select __buffersLoaded :+ 1 r = lua_pcall( _state, 0, 0, 0 ) MemFree( mem ) Select ( r ) Case 1 DebugLog "Lua runtime error encountered during lua_pcall" Case 4 DebugLog "Lua memory allocation error encountered during lua_pcall" Case 5 DebugLog "Error occurred while running the error handler function during lua_pcall" End Select End Method Rem bbdoc: Tells the Lua state to execute a string or the contents of a stream (stream takes priority). EndRem Method Do( url:Object, length%, name$ ) Validate( ) Local p:String = "" Local s:TStream = OpenStream( url, True, False ) If ( s = Null ) p = String( url ) If ( p ) DoString( p ) Return End If EndIf Local mem@[length] s.ReadBytes( mem, length ) s.Close( ) s = Null 'Local r:Int = lua_load( _state, _lsb, [length,Int(mem)], name ) Local r:Int = lua_load( _state, _lsb, [length, Int(Varptr mem[0])], name ) Select ( r ) Case 1 DebugLog "Lua runtime error encountered during lua_load:~n"+PopString( ) Case 2 DebugLog "Lua file error encountered during lua_load:~n"+PopString( ) Case 3 DebugLog "Lua syntax error encountered during lua_load:~n"+PopString( ) End Select r = lua_pcall( _state, 0, 0, 0 ) Select ( r ) Case 1 DebugLog "Lua runtime error encountered during lua_pcall:~n"+PopString( ) Case 4 DebugLog "Lua memory allocation error encountered during lua_pcall:~n"+PopString( ) Case 5 DebugLog "Error occurred while running the error handler function during lua_pcall:~n"+PopString( ) End Select End Method Rem bbdoc: Registers a callback so it's accessible to Lua scripts. EndRem Method RegisterFunction( name$, func:Int( state@ Ptr ) ) Validate( ) lua_pushlstring( _state, name, name.Length ) lua_pushcclosure( _state, func, 0 ) lua_rawset( _state, LUA_GLOBALSINDEX ) End Method Rem bbdoc: Pops @n elements from the stack. EndRem Method Pop( n:Int = 1 ) Validate( ) If Size( ) = 0 Then Return lua_settop( _state, -(n+1) ) End Method Rem bbdoc: Gets a value from a table.

To use this, you have to push the key (be it a number or string or what have you) and call this with the correct index of the table. The key will be popped and the resulting value will be pushed onto the stack. EndRem Method GetTable( idx% = -2 ) Validate( ) If Not Is(idx, LUA_TTABLE) Then DebugLog "Value at "+idx+" is not a table" Return EndIf lua_gettable( _state, idx ) End Method Rem bbdoc: Gets a value from a table.

To use this, you have to push the key (be it a number or string or what have you) and value, then call this with the correct index of the table. The key and value will be popped from the stack, no cleanup is neccessary. EndRem Method SetTable( idx% = -3 ) Validate( ) If Not Is(idx, LUA_TTABLE) Then DebugLog "Value at "+idx+" is not a table" Return EndIf lua_settable( _state, idx ) End Method Rem bbdoc: Creates a table and pushes it onto the stack. EndRem Method CreateTable( ) Validate( ) lua_createtable( _state ) End Method Rem bbdoc: Pushes a string onto the stack. EndRem Method PushString( s$ ) Validate( ) lua_pushlstring( _state, s, s.Length ) End Method Rem bbdoc: Pushes a boolean value onto the stack. True or False only. EndRem Method PushBool( b% ) Validate( ) lua_pushboolean( _state, b ) End Method Rem bbdoc: Pushes a number onto the stack. EndRem Method PushNumber( n! ) Validate( ) lua_pushnumber( _state, n ) End Method Rem bbdoc: Pushes a nil (Null) value onto the stack. This is not the same as pushing a Null pointer onto the stack. EndRem Method PushNil( ) Validate( ) lua_pushnil( _state ) End Method Rem bbdoc: Pushes a pointer (light userdata) onto the stack. EndRem Method PushPtr( p@ Ptr ) Validate( ) lua_pushlightuserdata( _state, p ) End Method ' Is( ) calls Validate, so calling Validate in these is unneccessary Rem bbdoc: Gets a string from @idx. This will DebugLog an exception if the value at idx is not a string. EndRem Method GetString$( idx% = -1 ) If ( Not Is( idx, LUA_TSTRING ) ) DebugLog "Data at "+idx+" is not a string ("+GetType(idx)+")" Return "" EndIf Return String.FromCString(lua_tolstring( _state, idx, Null )) End Method Rem bbdoc: Gets a boolean from @idx. This will DebugLog an exception if the value at idx is not a boolean. EndRem Method GetBool%( idx% = -1 ) If ( Not Is( idx, LUA_TBOOLEAN ) ) DebugLog "Data at "+idx+" is not a bool ("+GetType(idx)+")" Return -1 EndIf Return lua_toboolean( _state, idx ) End Method Rem bbdoc: Gets a number from @idx. This will DebugLog an exception if the value at idx is not a number. EndRem Method GetNumber!( idx% = -1 ) If ( Not Is( idx, LUA_TNUMBER ) ) DebugLog "Data at "+idx+" is not a number ("+GetType(idx)+")" Return 0 EndIf Return lua_tonumber( _state, idx ) End Method Rem bbdoc: Gets a pointer (light userdata) from @idx. This will DebugLog an exception if the value at idx is not a pointer. EndRem Method GetPtr@ Ptr( idx% = -1 ) If ( Not Is( idx, LUA_TLIGHTUSERDATA ) ) DebugLog "Data at "+idx+" is not a pointer ("+GetType(idx)+")" Return Null EndIf Return lua_touserdata( _state, idx ) End Method Rem bbdoc: Gets a string from the top of the stack and pops it from the stack. If the value at the top of the stack is not a string an exception will be DebugLogn. EndRem Method PopString$( ) Local r$ = GetString( ) Pop( 1 ) Return r End Method Rem bbdoc: Gets a boolean from the top of the stack and pops it from the stack. If the value at the top of the stack is not a boolean an exception will be DebugLogn. EndRem Method PopBool%( ) Local r% = GetBool( ) Pop( 1 ) Return r End Method Rem bbdoc: Gets a number from the top of the stack and pops it from the stack. If the value at the top of the stack is not a number an exception will be DebugLogn. EndRem Method PopNumber!( ) Local r! = GetNumber( ) Pop( 1 ) Return r End Method Rem bbdoc: Gets a pointer (light userdata) from the top of the stack and pops it from the stack. If the value at the top of the stack is not a pointer an exception will be DebugLogn. EndRem Method PopPtr@ Ptr( ) Local r@ Ptr = GetPtr( ) Pop( 1 ) Return r End Method Rem bbdoc: Returns the type of value at @idx.

This can be any of the following values:
EndRem Method GetType%( idx% = -1 ) Validate( ) Return lua_type( _state, idx ) End Method Rem bbdoc: Returns whether or not the value at @idx is of @_type. EndRem Method Is%( idx%, _type% ) Validate( ) Return ( lua_type( _state, idx ) = _type ) End Method Rem bbdoc: Returns the lua_State pointer. Endrem Method GetState@ Ptr( ) Validate( ) Return _state End Method Rem bbdoc: Calls a global function.

You have to push all arguments onto the stack before calling the function. EndRem Method Call( name$, args%, results% ) PushString( name ) GetTable( LUA_GLOBALSINDEX ) If ( args > 0 ) lua_insert( _state, -(args+1) ) Local r:Int = lua_pcall( _state, args, results, 0 ) Select ( r ) Case 1 DebugLog "Lua runtime error encountered during lua_pcall ("+name+"):~n"+PopString( ) Case 4 DebugLog "Lua memory allocation error encountered during lua_pcall ("+name+"):~n"+PopString( ) Case 5 DebugLog "Error occurred while running the error handler function during lua_pcall ("+name+"):~n"+PopString( ) End Select End Method Rem bbdoc: Sets a global string. EndRem Method SetGlobalString( name$, s$ ) PushString( name ) PushString( s ) SetTable( LUA_GLOBALSINDEX ) End Method Rem bbdoc: Sets a global boolean. EndRem Method SetGlobalBool( name$, b% ) PushString( name ) PushBool( b ) SetTable( LUA_GLOBALSINDEX ) End Method Rem bbdoc: Sets a global number. EndRem Method SetGlobalNumber( name$, n! ) PushString( name ) PushNumber( n ) SetTable( LUA_GLOBALSINDEX ) End Method Rem bbdoc: Sets a global pointer. EndRem Method SetGlobalPtr( name$, p@ Ptr ) PushString( name ) PushPtr( p ) SetTable( LUA_GLOBALSINDEX ) End Method Rem bbdoc: Gets a global string. EndRem Method GetGlobalString$( name$ ) PushString( name ) GetTable( LUA_GLOBALSINDEX ) Return PopString( ) End Method Rem bbdoc: Gets a global boolean. EndRem Method GetGlobalBool%( name$ ) PushString( name ) GetTable( LUA_GLOBALSINDEX ) Return PopBool( ) End Method Rem bbdoc: Gets a global number. EndRem Method GetGlobalNumber!( name$ ) PushString( name ) GetTable( LUA_GLOBALSINDEX ) Return PopNumber( ) End Method Rem bbdoc: Gets a global pointer. EndRem Method GetGlobalPtr@ Ptr( name$ ) PushString( name ) GetTable( LUA_GLOBALSINDEX ) Return PopPtr( ) End Method Rem bbdoc: Returns the size of the stack. EndRem Method Size%( ) Validate( ) Return lua_gettop( _State ) End Method End Type