Access userdata content in Corona SDK - c

From an in-app server, I receive a table and inside this table there's a key marked as userdata. I red this type is there to allow arbitrary C data to be stored inside Lua variables. Is it possible to read/access its content from Lua?

Lua can't read data from userdata, unless you write native functions that will read and return bytes from userdata in some way you will find convenient - as array of numbers, as string, or maybe just returning single byte at specified index.Maybe your host app/framework already has these functions, but Lua itself definitely can't do that.
Corona SDK's page for userdata only quotes Lua's doc, telling basically the same - there's no operations on userdata in Lua, except assignment and identity test.

Related

C and Lua - Pass native object instance to native Lua function

C functions that are passed to Lua to so that Lua can call native functions are static functions and thus not related to an object instance.
In my application, I have multiple sessions. Each session runs on its own thread, has its own data and its own scripts, and a script of the session N must be able to access the data of that session N.
The problem is that when you register a native C function to be callable from Lua, I can't pass the instance of the session object to make it available in the static Lua function.
One possibility could to be store the instance of the session into a static variable that can be called from the static C function (called from Lua), but this looks dirty and would require synchronization that could cause some scripts to hang.
A second possibility might be to create an Lua object that represents the session and call member methods on it so that, in my C function, I would have a way to access the Lua object representing the session ("this") and retreive the actual native session instance represented by this object. But I have no idea how to do that.
Is there a way to create Lua objects representing native object instances in Lua so that native Lua functions would have access to that native object instance ?
When you register a C function with Lua, you can store additional values as so-called "upvalues". The C function can then retrieve those values when it's called:
// ...
// push session instance pointer
lua_pushlightuserdata( L, (void*)get_current_session() );
// create a closure with one upvalue
lua_pushcclosure( L, my_static_C_function, 1 );
// ... (the resulting Lua function is at the stack top now)
In your static C function you access the instance data like this:
static int my_static_C_function( lua_State* L ) {
session_t* instance = (session_t*)lua_touserdata( L, lua_upvalueindex( 1 ) );
instance->do_something();
return 0;
}
Since each session has its own thread, why don't you link them together?
Whenever your function is called, get the session from the current thread.
You might want to take a look at the manuals about userdata.
Since "Each session runs on its own thread" you could simply save session data as static thread-local.
Better would be to transport session data by userdata, with a metatable bound for associated functions, and don't rely on static stuff.
As last alternative, let's combine: save session data as userdata/pointer Lua-state-local.
In all cases you have to care about class instances destruction because userdata are freed in C-style, same as thread data.

Lua (LuaJit) and object lifetime in C

I use LuaJit for extending a plain C application (using the Lua C API). The host application does manage memory for a lot of objects that I have written wrappers for in Lua.
Now I would like to be able to delete objects from within the lua function, i.e. implement a delete function. I would like to illustrate the problem at hand with the following outline of the problem.
Basically my lua user data structure looks something like this.
struct my_lua_container {
size_t obj_db_index;
};
where obj_db_index is an index for the local object database. With the Lua C API I have created a lua-function query_object(...) that retrieves a lua metatable based on this user data and offering an API for managing the db object.
I am now planning to introduce a method my_db_object:delete() in the metatable API. :delete() could invalidate my_db_object by overwriting the variable with 0 or setting another member variable. The problem however is, that all references to the deleted object ought to be invalidated. Consider this lua code:
local p = query_object("1")
local q = query_object("1")
p:delete()
q:do_something() -- <=== q still contains a obj_db_index
Now I wonder how to solve this potential conflict. The two main problems are:
An invalid obj_db_index could be an invalid index. This is actually probably caught by the code already, so it isn't pretty but alright
after deletion, the index might be reused and this could lead to subtle errors when other references still use the old index.
What are strategies to deal with this?
My idea might be a little time-consuming but this would be ok in the event of deletion:
Is there some Introspection that I can perform on user data objects? Like iterating over all user data objects with the same type in order to invalidate my_db_index when the deletion is triggered
Maybe a little late, but… The solution is to put new objects into weak table and never create objects already stored there.
-- this should be really C, but for readability, we write it in Lua pseudocode
registry.my_cache = setmetatable({ }, { __mode = "v" })
function push_object(db_id)
local object = registry.my_cache[db_id]
if object == nil then
object = lua_newuserdata(db_id)
registry.my_cache[db_id] = object
end
end
assert(push_object(1) == push_object(1))
Now only unique db_id's go from C side to Lua side, problem almostly disappeared.
But there is one more detail to take care of. Garbage-collection of userdata has two phases: finalization and removal from weak tables. There are moments, when userdata is finalized, but still present in weak table, so the code above may return finalized userdata to the user. Additional check should be made, and if ud is finalized, it should be manually removed from table first.
function push_object(db_id)
local object = registry.my_cache[db_id]
-- check vitality first
if is_finalized(object) then
registry.my_cache[db_id] = nil
object = nil
end
if object == nil then
object = lua_newuserdata(db_id)
registry.my_cache[db_id] = object
end
end
How you know whether userdata is finalized is up to your implementation of finalization method (metatable.__gc).

Access Lua variables in userdata from the C api

I am working on a project written in C++ which uses Lua as a scripting language.
In order to facilitate debugging we implemented a network debugger which receives Lua code, runs it, encodes the return values in Json and sends that string back.
I managed to implement that for tables, but now I am stuck with variables stored in userdata.
E.g. I have this Lua code:
Elements.Avatar.testVar = 5
Elements.testVar = 15
return Elements
// result
{
"result0": "{Application:userdata; Avatar:userdata; Physics:userdata; testVar:15; }"
}
Application, Avatar and Physics are objects that have been created in C++. The two testVars however have been created in the script above.
Elements is a table, so I can list all elements, but Avatar.testVar seems to be hidden because Avatar is a LUA_TUSERDATA.
Does anyone have an idea how I can detect variables that have been added to userdata in Lua?
There is no such thing as a "variable stored in userdata", At least, not as far as Lua is concerned. From Lua's perspective, userdata is a giant black box. All Avatar.testVar = 5 does is call the metamethod __newindex in Avatar with the string testVar and the new value 15. How your C++ metamethod (because only C++ code can put metamethods on userdata) interprets this is entirely up to your code.
So it can't be done from Lua. Your code will need to provide debugging hooks. Lua 5.2 allows you to implement the __pairs and __ipairs metamethods, which the pairs and ipairs functions can use to iterate over your values. Outside of that, you're on your own for querying what does and doesn't exist in a userdata.

How to inspect userdata in lua

I am using inspect.lua to inspect table to string.
But, if the value is a userdata, it returns just <userdata 1>
I really need to know what the userdata type is, what the userdata value is, it's very important for debuging, I don't want do it in any IDE, I just want something can help me debug by print staffs.
You cannot.
From the manual :
The type userdata is provided to allow arbitrary C data to be stored in Lua variables. A userdata value is a pointer to a block of raw memory. [...] Userdata has no predefined operations in Lua, except assignment and identity test.
As indicated by #Eric, the only thing you can do from Lua is inspect the metatable :
print(inspect(getmetatable(someuserdata)))
If you are using the C API, you should be able to register a custom function that prints whatever is held by the block.
If the userdata metatable was created with luaL_newmetatable it contains an entry __name containing the userdatas type (since Lua version 5.3), see https://www.lua.org/manual/5.3/manual.html#luaL_newmetatable. Unfortunately this feature is still not widely used.

Store a Lua function?

Calling a Lua function from C is fairly straight forward but is there a way to store a Lua function somewhere for later use? I want to store user defined Lua functions passed to my C function for use on events, similar to how the Connect function works in wxLua.
check the registry (luaL_ref()). it manages a simple table that lets you store any Lua value (like the function), and refer to it from C by a simple integer.
Building on Javier's answer, Lua has a special universally-accessible table called the registry, accessible through the C API using the pseudo-index LUA_REGISTRYINDEX. You can use the luaL_ref function to store any Lua value you like in the registry (including Lua functions) and receive back an integer that can be used to refer to it from C:
// Assumes that the function you want to store is on the top of stack L
int function_index = luaL_ref(L, LUA_REGISTRYINDEX);
The easiest way to do this is for your function to take a "name" and the lua function text. Then you create a table in the interpreter (if it doesn't exist) and then store the function in the table using the named parameter.
In your app just keep hold of a list of function names tied to each event. When the event fires just call all the functions from your table whose key matches the names in the list.

Resources