1

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 ?

1
  • 1
    Just a quick tip: "Lua" is a name, not an acronym. That's why it's written "Lua", not "LUA" ;) For more info, see lua.org/about.html#name :) Commented Feb 9, 2016 at 11:19

3 Answers 3

2

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;
}
Sign up to request clarification or add additional context in comments.

6 Comments

This would be similar to the last solution in my answer but "Lua-function-local". It's a good answer in case he needs session data just for one function, otherwise C closures have some costs and putting session data into the registry is smarter.
@siffiejoe Thanks for your help. That's seems close to what I need. I'll keep reading the documentation and use this, unless I find a more elegant way while reading the documentation.
@Youka Why would this solution be good only if I need to access my native session instance from only one native function ?
@Virus721 A Lua C function without upvalues is just a pointer to the C function (pure function). A closure is another type and have to manage upvalues in a header. Creating, storing and GCing the same upvalue for each function has his costs in memory and performance. The registry instead needs just one creation, space for one value and GCs just when the stack is destroyed.
@Virus721 Furthermore each function call needs to prepare upvalues (beside the stack). At the end you have a lot of duplicates to care about repeatedly instead of one weak data.
|
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.

2 Comments

Thanks for your help. Though retreiving an instance based on the current thread doesn't seem very straight forward. I'll keep this solution if I can't find something more elegant.
You could wrap the C functions in Lua and store the needed data Lua-side, using coroutine.thread(). It's probably better to do it C-side, but doing it Lua side can work. The code calling Func(...) would actually be calling ActualCFunc(variableFromThread,...)
0

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.

1 Comment

Thanks for your help. I will try do something based on that and find more info in the documentation. Also I can't use thread local because I'm using C++ as a common code base for Windows CE and Android and I canot use C++11 as I can't use more recent versions of Visual Studio than the 2008.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.