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.
Related
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.
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).
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.
Working with C and Win32, I would like to know how to implement a secondary OpenGL thread for loading resources(textures and VBOs).
From what I found, this should be done with wglShareLists(), but I am unsure about how to set up the secondary thread:
Do I need a new device context or only a new rendering context?
What wgl functions do I need to call?
You don't need a new context because you can reuse the same device context of the first one. Btw, you can specify another device context, but depending on your platform you should take care about it (on Windows, device contextes must have the same pixel format), otherwise you could fail to share objects between two contextes
Create both context in the main thread, the second one sharing with the first one. Then, make the first one current on the main thread, while making the other one current on the secondary thread.
Note that you can share with any render context: all sharing contextes "see" the same object by its name, indeed they share an object name space. Two different object name spaces (i.e. two non-sharing contextes) can have defined the same object (i.e. texture object name is 1), but the same name actually points to different object depending on the current context.
Objects created by the secondary thread are visible concurrently and consistently. However, not all objects can be shared across contextes. Keep in mind that sometimes it happens that the driver supports unexpected objects, and other times it happens that driver doesn't support correctly an expected object.
OpenGL is becoming an object oriented language. You can see a certain pattern for creating objects:
Generate name (GenTextures, GenBuffers)
Define object (BindTexture, BindBuffer)
Object existence (IsTexture, IsShader, IsFramebuffer)
Delete name (and object)
(Note that an object created with Gen routines exists only when they are bound)
Object classes could be
Display lists
Texture objects
Buffer objects
Shader objects and program objects
Renderbuffer objects
Framebuffer objects
Query objects
Sync objects
Transform feedback objects
I would suggest to use a "runtime" test, like the following:
private bool TestSharingObject(RenderContext rContextShare)
{
uint texture = 0;
// rContextShader is a context sharing with this RenderCOntext
this.MakeCurrent(true);
if (Caps.TextureObject.Supported == true) {
// Generate texture name
Gl.GenTextures(1, out texture);
// Ensure existing texture object
Gl.BindTexture(Gl.TEXTURE_2D, texture);
Gl.BindTexture(Gl.TEXTURE_2D, 0);
// Self test
if (Gl.IsTexture(texture) == false)
throw new NotSupportedException();
}
// Make current sharing context
rContextShare.MakeCurrent(true);
return ((texture != 0) && (Gl.IsTexture(texture) == true));
}
Another suggestion would be to run on secondary thread operations that are CPU intensive, and not directly affecting drawing system windows buffers. A good example would be a shader compilation, since the compilation runs on CPU side; keep also in mind that the driver could async your operations, and that OpenGL implementations may pipeline different operations..
Load resources however you need to in your secondary thread and then pass ownership of them back to your primary for the GL calls.
Sharing "lists" between GL contexts should work. Doing all your GL calls on your primary thread does work :)
It works!, only if wglShareLists is done by the main thread for all the worker thread.
Using message map, pass the reference of rendering context and make the main thread create the rendering context, use wglShareLists by main thread alone. Then call wglMakeCurrent on the worker thread with the rendering context created by main thread. It is imperative that wglShareLists is called before any gl operation is done on the rendering context. This is due to the requirement on parameter hglrc2(the OpenGL rendering context to share display lists with hglrc1), that it should not contain any existing display lists when wglShareLists is called.
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.