More Lua functionality

BlitzMax Forums/BlitzMax Programming/More Lua functionality

JoshK(Posted 2009) [#1]
I think I need to implement Lua myself to understand it completely. Below is my code for procedural functions:


1) How can I specify default arguments when a function is registered?

2) How can I expose a type? I want to know how to hard-code this simple class and method so it can be called from Lua:
Type MyType

	Method MyMethod()
		Print "Method!"
	EndMethod

EndType



N(Posted 2009) [#2]
1) You don't. You check to see how many arguments are on the stack when the function is called and decide based on that.

E.g.,
Function defval:Int(state:Byte Ptr)
	Local top:Int = lua_gettop(state)
	
	Local arg1:Int = lua_tointeger(state, 1)
	Local arg2:Int = 5 ' default value
	
	If top > 1 Then
		arg2 = lua_tointeger(state, 2)
	EndIf
	
	' ...
	
	Return 0
End Function


2) This is a bit of a non-answer, since I can't tell you how to do this without 1) going way over your head at the moment and 2) writing a ton of commented example code, so make of it what you will. I'm definitely not planning on doing #2, at any rate.

There are a lot of different ways. You could attach a metatable to it to return a glue function when indexed, create a table and put glue functions in it, expose just the glue functions in a procedural sort of API. Each implementation is different, and writing an example would take a good while, so I'll let you ponder the implementation details on your own.

What I've been looking at is using the first option in conjunction with some scripts I wrote to generate glue functions (so I don't have to write the code myself). Most of the code pertaining to the scripts is on Github (under BBDocugen), but none of that'll run under Windows unless you can get Ruby 1.9.1 built under it (I haven't been able to) or want to port all the regex code to the Oniguruma gem.

On the other hand, pushing an object itself is fairly easy:
Global lua_pushlightobject(state@ Ptr, obj:Object) = Byte Ptr(lua_pushlightuserdata)

' ...

lua_pushlightobject(state, someObject)


This tends to only work if you're building threaded apps. When building a regular application using the refcounting GC, you have to:
1) Retain the object
2) Create a full userdata and set its value to the object
3) Attach a metatable to the userdata that decrements the reference counter for the object when the userdata is collected by Lua's GC

Which is fairly simple. MaxLua does this, LRef does this, etc. so there's no shortage of examples of how it's done.


JoshK(Posted 2009) [#3]
Right now I am thinking the glue functions would look something like this. I can auto-generate this code from a source file, but I am not clear on the integration with Lua:

Type TFoo

	Field bar:Int
	
	Method do:Int(in:String)
	EndMethod

EndType

Function glue_TFoo_Method_do(L:Byte Ptr,o:TFoo)
	Local in:String
	in=lua_CheckString(L)
	lua_pushnumber(o.do(in))
EndFunction

Function glue_TFoo_SetField_bar(L:Byte Ptr,o:TFoo)
	o.bar=lua_CheckInteger(L)
EndFunction

Function glue_TFoo_GetField_bar(L:Byte Ptr,o:TFoo)
	lua_pushnumber(L,o.bar)
EndFunction



JoshK(Posted 2009) [#4]
Going off of this page:
http://www.lua.org/notes/ltn005.html

...I've set up parts of this test, but I still don't understand how to make it work. Any ideas? If I can hard-code a test to make sure all the features work right, then I can just auto-generate this code. But first I need to figure out what I am doing.

Local L:Byte Ptr
L=luaL_newstate()
luaL_openlibs(L)

lua_newtable(L)
lua_pushstring(L,"bar")
lua_pushnumber(L,3)
lua_pushstring(L,"do")
lua_pushnumber(L,3)
lua_pushcclosure(L,thunk,1)


'This is the class I want to expose
Type TFoo

	Field bar:Int=3
	
	Method do:Int(in:String)
	EndMethod

EndType


'Here is the "thunk" function
Function thunk:Int(L:Byte Ptr)
	
EndFunction


'These functions provide a way to do things to the class
Function glue_TFoo_Method_do(L:Byte Ptr,o:TFoo)
	Local in:String
	in=lua_CheckString(L)
	lua_pushnumber(o.do(in))
EndFunction

Function glue_TFoo_SetField_bar(L:Byte Ptr,o:TFoo)
	o.bar=lua_CheckInteger(L)
EndFunction

Function glue_TFoo_GetField_bar(L:Byte Ptr,o:TFoo)
	lua_pushnumber(L,o.bar)
EndFunction