Code archives/Miscellaneous/Lua-Scriptable Type
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| This is sort of a rudimentary example of using LuGI to bind Lua functions to objects in Lua. It could be expanded upon (e.g., binding closures for different messages and such), but it works well enough for the sake of example. Speaking of examples, here's some code and a script to accompany it: woop.bmx woop.lua Bear in mind that this requires the most recent version of LuGI's master branch, since I added a handy method for binding glue functions to types. This was already possible, it just required you to be aware of the private API, which seems like a bad idea to me since it's only documented in the headers. | |||||
SuperStrict
?Debug
Import LuGI.Generator
?
Import LuGI.Core
Include "scriptable_glue.bmx"
'LUGI_CATEGORIES="scriptable"
'GenerateGlueCode("scriptable_glue.bmx")
'End
Type Scriptable {expose disablenew category="scriptable"}
Field _state@Ptr
Field _closures%=-2
Method Delete()
Dispose
End Method
Method Init:Scriptable(state@Ptr) {hidden}
_state = state
lua_newtable(state)
_closures = luaL_ref(state, LUA_REGISTRYINDEX)
Return Self
End Method
Method GetScriptFunc:Int(L@Ptr, name$)
Assert L=_state Else "Invalid Lua state for scriptable object"
If _closures = -1 Then
Return False
EndIf
lua_rawgeti(L, LUA_REGISTRYINDEX, _closures) '-1=table
lua_pushstring(L, name) '-2=table,-1=name
lua_gettable(L, -2) '-2=table,-1=value
If lua_isfunction(L, -1) Then
lua_remove(L, -2) '-1=value
Return True
Else
lua_pop(L, 2) 'clear
Return False
EndIf
End Method
Method Dispose()
If _state And _closures <> -2 Then
If GetScriptFunc(_state, "Dispose") Then
lua_pushbmaxobject(_state, Self)
lua_pcall(_state, 1, 0, 0)
EndIf
luaL_unref(_state, LUA_REGISTRYINDEX, _closures)
_closures = -2
EndIf
End Method
Method ToString$()
Return "Scriptable"
End Method
End Type
'metadata isn't used since there's currently no way to use reflection to grab it for functions anyway
Function l_Scriptable_SetScript%(L@Ptr) {bindto="Scriptable" as="SetScript"}
Local so:Scriptable
If lua_gettop(L) <> 3 Then
lua_pushstring(L, "Invalid number of arguments to SetScript - expected 3, got "+lua_gettop(L))
lua_error(L)
EndIf
luaL_argcheck(L, lua_isbmaxobject(L, 1) And (Not lua_isnoneornil(L, 1)), 1, "must be a subclass of the Scriptable type")
luaL_argcheck(L, lua_isstring(L, 2), 2, "must be a string naming the routine added to the object")
luaL_argcheck(L, lua_isfunction(L, 3) Or lua_isnil(L, 3), 3, "must be a function or nil")
so = Scriptable(lua_tobmaxobject(L, 1))
If Not so Then
luaL_argerror(L, 1, "must be a subclass of the Scriptable type")
EndIf
If so._closures <> -2 Then
lua_rawgeti(L, LUA_REGISTRYINDEX, so._closures)
lua_insert(L, -3)
lua_settable(L, -3)
EndIf
End Function
Function l_Scriptable_GetScript%(L@Ptr)
Local so:Scriptable
luaL_argcheck(L, lua_isbmaxobject(L, 1) And (Not lua_isnoneornil(L, 1)), 1, "must be a subclass of the Scriptable type")
so = Scriptable(lua_tobmaxobject(L, 1))
If Not so Then
luaL_argerror(L, 1, "must be a subclass of the Scriptable type")
EndIf
Local args:Int = lua_gettop(L)
For Local i:Int = 2 To args
luaL_argcheck(L, lua_isstring(L, i), i, "must be a string naming a requested routine")
If Not so.GetScriptFunc(L, lua_tostring(L, i)) Then
lua_pushnil(L)
EndIf
Next
Return args-1
End Function
BindFunctionToType(l_Scriptable_SetScript, "SetScript", TTypeID.ForName("Scriptable"))
BindFunctionToType(l_Scriptable_GetScript, "GetScript", TTypeID.ForName("Scriptable")) |
Comments
| ||
| Thanks for all the stuff you've posted to do with Lua. It's helping me to understand the language and how to implement it in BlitzMax a lot. |
| ||
| Updated this to make it slightly more versatile (and probably usable for whatever you wanted now). You can now assign functions with names, so you could have an "Update" routine, a "ReceiveHitDamage" routine, etc. Also fixed a bug from when I forgot to use SuperStrict - LUA_NOREF is apparently undefined. Odd, but it's just -2, so I changed it out. |
Code Archives Forum