Code archives/Miscellaneous/Simple OO Lua Interface
This code has been declared by its author to be Public Domain code.
Download source code
| First off, this is a module, it goes in Cower.LuaInterface (obviously it's not required, you can place it anywhere you like). If you don't know how to add modules, then this is likely not something that will help you. This is a simple object oriented interface to Lua to simplify useage. The idea is to derive a class from the base that implements data types and 'features' specific to your application. An example of using the base itself without any extension(s): Strict Local l:Lua = Lua.Create( ) Function lua_Print( state@ Ptr ) Local l:BaseLuaInterface = BaseLuaInterface.FromState( state ) Local s:Int = l.Size( ) Local i:Int For i = 1 To s Select l.GetType( i ) Case LUA_TNUMBER Print l.GetNumber( i ) Case LUA_TBOOLEAN Print l.GetBool( i ) Case LUA_TSTRING Print l.GetString( i ) End Select Next Return 0 End Function l.RegisterFunction( "lPrint", lua_Print ) l.SetGlobalString( "aGlobal", "the value of a global variable" ) l.DoString( "lPrint( ~qPie~q, 5.4321, true, aGlobal )" ) l = Null Input( "" ) An example of extending it... Type CColor Field Red! Field Green! Field Blue! Field Alpha! End Type Type GLua Extends Lua Method PushColor( col:CColor ) Validate( ) CreateTable( ) PushString( "red" ) PushNumber( col.Red ) SetTable( ) PushString( "green" ) PushNumber( col.Green ) SetTable( ) PushString( "blue" ) PushNumber( col.Blue ) SetTable( ) PushString( "alpha" ) PushNumber( col.Alpha ) SetTable( ) End Method Method GetColor:CColor( idx% = -1 ) Validate( ) If ( idx < 0 ) idx :+ Size( ) Local c:CColor = New CColor PushString( "red" ) GetTable( idx ) PushString( "Green" ) GetTable( idx ) PushString( "Blue" ) GetTable( idx ) PushString( "Alpha" ) GetTable( idx ) c.Alpha = PopNumber( ) c.Blue = PopNumber( ) c.Green = PopNumber( ) c.Red = PopNumber( ) Return c End Method End Method |
Rem
I do not support this code and will most likely not help you if you ask any
questions, so I'd advise trying to help yourself.
EndRem
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
Function _ls_alloc@ Ptr( ud@ Ptr, p@ Ptr, osize%, nsize% )
If p Then
If nsize = 0 Then
MemFree( p )
Else
p = MemExtend( p, osize, nsize )
EndIf
Else
If nsize = 0 Then
Return Null
Else
Return MemAlloc( nsize )
EndIf
EndIf
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.<br/>
<br/>
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.<br/>
<br/>
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).<br/>
<br/>
When extending this class, you should override this function so that it creates the extended class. That, or you can just do <pre>New YourExtendedClass.Reset( state, True/False )</pre>.
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( lua_newstate( _ls_alloc, Null ), 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
If name = "" Or name = Null Then
name = url.ToString()
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 )
?Debug
DebugLog "Registering 0x"+Hex(Int(Byte Ptr(func)))+" as "+name
?
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.<br/>
<br/>
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.<br/>
<br/>
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( narr%=0, nrec%=0 )
Validate( )
lua_createtable( _state, narr, nrec )
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 <em>not</em> 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)+")"
Select GetType( idx )
Case LUA_TUSERDATA
DebugLog "Data at "+idx+" is a pointer: 0x"+Hex(Int(GetPtr(idx)))
Case LUA_TBOOLEAN
DebugLog "Data at "+idx+" is a boolean: "+GetBool(idx)
Case LUA_TNUMBER
DebugLog "Data at "+idx+" is a number: "+GetNumber(idx)
Case LUA_TNIL
DebugLog "Data at "+idx+" is nil"
Case LUA_TNONE
DebugLog "Data at "+idx+" is None"
Default
End Select
Return Null
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)+")"
Select GetType( idx )
Case LUA_TUSERDATA
DebugLog "Data at "+idx+" is a pointer: 0x"+Hex(Int(GetPtr(idx)))
Case LUA_TSTRING
DebugLog "Data at "+idx+" is a string: <<<"+GetString(idx)+">>>"
Case LUA_TNUMBER
DebugLog "Data at "+idx+" is a number: "+GetNumber(idx)
Case LUA_TNIL
DebugLog "Data at "+idx+" is nil"
Case LUA_TNONE
DebugLog "Data at "+idx+" is None"
Default
End Select
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)+")"
Select GetType( idx )
Case LUA_TSTRING
DebugLog "Data at "+idx+" is a string: <<<"+GetString(idx)+">>>"
Case LUA_TBOOLEAN
DebugLog "Data at "+idx+" is a boolean: "+GetBool(idx)
Case LUA_TUSERDATA
DebugLog "Data at "+idx+" is a pointer: 0x"+Hex(Int(GetPtr(idx)))
Case LUA_TNIL
DebugLog "Data at "+idx+" is nil"
Case LUA_TNONE
DebugLog "Data at "+idx+" is None"
Default
End Select
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)+")"
Select GetType( idx )
Case LUA_TSTRING
DebugLog "Data at "+idx+" is a string: <<<"+GetString(idx)+">>>"
Case LUA_TBOOLEAN
DebugLog "Data at "+idx+" is a boolean: "+GetBool(idx)
Case LUA_TNUMBER
DebugLog "Data at "+idx+" is a number: "+GetNumber(idx)
Case LUA_TNIL
DebugLog "Data at "+idx+" is nil"
Case LUA_TNONE
DebugLog "Data at "+idx+" is None"
Default
End Select
Return Null
EndIf
Return lua_touserdata( _state, idx )
End Method
Rem
Method PushMatrix( m:Matrix )
CreateTable( )
Local p! Ptr = Double Ptr(m.GetPtr( ))
For Local i:Int = 0 To 15
PushNumber( i )
PushNumber( p[i] )
SetTable( )
Next
End Method
Method GetMatrix:Matrix( idx%=-1 )
If Not Is(idx, LUA_TTABLE) Then
Return Null
EndIf
Local m:Matrix = New Matrix
Local p! Ptr = Double Ptr(m.GetPtr( ))
For Local i:Int = 0 To 15
PushNumber( i )
GetTable( -3+idx )
p[i] = PopNumber( )
Next
Return m
End Method
Method PopMatrix:Matrix( )
Local m:Matrix = GetMatrix( )
Pop( )
Return m
End Method
Method PushVector( v:Vector3 )
CreateTable( )
PushString( "x" )
PushNumber( v.x )
SetTable( )
PushString( "y" )
PushNumber( v.y )
SetTable( )
PushString( "z" )
PushNumber( v.z )
SetTable( )
End Method
Method GetVector:Vector3( idx:Int = -1 )
If Not Is(idx,LUA_TTABLE) Then
Return Null
EndIf
Local v:Vector3 = New Vector3
PushString("x")
GetTable( idx-1 )
v.x = PopNumber( )
PushString("y")
GetTable( idx-1 )
v.y = PopNumber( )
PushString("z")
GetTable( idx-1 )
v.z = PopNumber( )
Return v
End Method
Method PopVector:Vector3( )
Local v:Vector3 = GetVector( )
Pop( )
Return v
End Method
EndRem
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.<br/>
<br/>
This can be any of the following values:<br/>
<ul>
<li>LUA_TNONE</li>
<li>LUA_TNIL</li>
<li>LUA_TBOOLEAN</li>
<li>LUA_TNUMBER</li>
<li>LUA_TSTRING</li>
<li>LUA_TUSERDATA</li>
<li>LUA_TTABLE</li>
<li>LUA_TFUNCTION</li>
<li>LUA_TTHREAD</li>
</ul>
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.<br/>
<br/>
You have to push all arguments onto the stack before calling the function.
EndRem
Method Call( name$, args%, results% )
If name.Length Then
PushString( name )
GetTable( LUA_GLOBALSINDEX )
EndIf
If args > 0 Then 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 |