LuaJIT strange issue

Started by LT, August 20, 2018, 18:11:33

Previous topic - Next topic

LT

I'm using the LuaJIT module and FFI.  Anyone else out there doing the same?

Anyway, I seem to have a problem with lua_topointer sometimes returning garbage, but only in Debug mode.  I've been speculating that Debug mode could be attaching data that confuses that function somehow.  Does anyone have some insight on this?

GW


I use a lot of luajt, Ive never used the lua_topointer function though.  What are you trying to do?


Does this help?
https://www.syntaxbomb.com/index.php/topic,62.msg581.html


LT

#2
Hi, thanks for your response.

I've been using LuaJIT extensively for years, but this issue is new (to me).  I've written a 3d engine with Lua scripting tied in and am maintaining most methods as FFI calls.  Returning an object from the FFI results in a CDATA and I use lua_topointer to convert it to a BMX object.  The vast majority of it works, but I'm having trouble specifically with arrays as return values.  Sometimes I get garbage, but it seems to only happen in Debug mode.

Actually, I have reason to believe something is also happening in Release, but it doesn't result in a crash.  Anyway, I'm only a few months away from releasing a game, so it's nail-biting time, as you can imagine.  :)

Derron

I am not using LuaJit (just tried if my game works with it instead of classic blitzmax-lua-bindings).

Arrays in Lua and BlitzMax differ somehow. Eg. my lua-exposing-script contains some comments by me reminding that I disabled the "new/modify blitzmax array" access from within Lua. It needs custom userdata and additional metatables to properly work).
So instead of allowing "blitzmaxobject.arr[bla] = x" I needed to have exposed helper functions "exposedType.SetBlitzMaxObject(bla, x)".

Passing arrays from BlitzMax to Lua works - but attention to the difference: Blitzmax is zero-based, Lua is 1-based:
Code (Blitzmax) Select

' create a table and load with array contents
Method lua_pushArray(obj:Object)
Local typeId:TTypeId = TTypeId.ForObject(obj)
'for "Null[]" the function ArrayLength(obj) fails with
'"TypeID is not an array type"
if typeId.Name() = "Null[]"
lua_newtable(getLuaState())
return
endif

Local size:Int = typeId.ArrayLength(obj)

lua_createtable(getLuaState(), size + 1, 0)

'lua is not zero based as BlitzMax is... so we have to add one
'entry at the first pos
' lua_pushinteger(getLuaState(), 0)
' lua_pushinteger(getLuaState(), -1)
' lua_settable(getLuaState(), -3)


For Local i:Int = 0 Until size
' the index +1 as not zerobased
lua_pushinteger(getLuaState(), i+1)
' lua_pushinteger(getLuaState(), i)

Select typeId.ElementType()
Case IntTypeId, ShortTypeId, ByteTypeId
lua_pushinteger(getLuaState(), typeId.GetArrayElement(obj, i).ToString().ToInt())
Case FloatTypeId
lua_pushnumber(getLuaState(), typeId.GetArrayElement(obj, i).ToString().ToFloat())
Case DoubleTypeId, LongTypeId
lua_pushnumber(getLuaState(), typeId.GetArrayElement(obj, i).ToString().ToDouble())
Case StringTypeId
Local s:String = typeId.GetArrayElement(obj, i).ToString()
lua_pushlstring(getLuaState(), s, s.length)
Case ArrayTypeId
Self.lua_pushArray(typeId.GetArrayElement(obj, i))
'for everything else, we just push the object...
Default
if typeId and typeId.ElementType().ExtendsType(ArrayTypeId)
Self.lua_pushArray(typeId.GetArrayElement(obj, i))
else
Self.lua_pushObject(typeId.GetArrayElement(obj, i))
endif
End Select

lua_settable(getLuaState(), -3)
Next
End Method




So, maybe you found a way of doing such array-modification but still miss some parts (while I already stopped right at the beginning).


bye
Ron

LT

That's the typical C API method.  I'm wrapping the pointer to a BMX array in a UserData and adding meta methods so they can be accessed in Lua just like index-based tables.  There is no need to add a zero element that way and no conversion happens unless you go in the other direction (i.e. turn Lua tables into UserData-wrapped Blitz arrays).

Anyway, after some fiddling around, I'm more convinced that the Debugger was adding something under the hood that was interfering with the lua_topointer function.  I have not been able to reproduce the bug since I simplified the push function, but I can't be sure it's a final solution.  Will keep an eye on it and post here if I learn anything new.

Thanks for your suggestions.

Derron

Is there a trimmed down version of the "meta tables"-stuff you add to make lua work with blitzmax arrays?
I would like to slim down some stuff for my (lua based) AI scripts - and direct array manipulation might be sometimes faster than a setXY(bla, bla, bla)-wrapper-method (albeit its good if you need ACL/access/write restrictions).


BTW I am not using LuaJIT as most of the processor-heavy stuff is already done in BlitzMax and scripts mostly do some simple loop-over-results, fetch best, call helper ... things.

bye
Ron

LT

#6
It's pretty involved and I believe FFI is LuaJIT only, but I can post something later if you like.  Here's a list of steps off the top of my head.

1. Make a weak global Lua table and add your reference to it (as lightuserdata), checking first to see if it exists.
2.  If not, push the object as userdata and add to it a metatable with __gc, __len, __index, and __newindex functions (C API, but fast enough).
3.  Use BBRETAIN to increment BMX's reference count.  The __gc function should use BBRELEASE.

In my version of this, the __len, __index, and __newindex functions are Lua-wrapped FFI functions that access the Blitz array.