|
|
||
|
Am 01.09.2013 01:25 schröbte Thomas Harning Jr.:
There is a constant you can modify that will give you data behind the lua_State pointer, can't recall it though... I've used it to store mutex data in projects.
The constant is LUAI_EXTRASPACE, but it is hard to use, because some necessary type definitions are hidden away in lstate.c. Here is what I came up with (for Lua 5.2):
Add the following to the end of luaconf.h:
-----------------------8<----------------------------
/* put you extra data here */
typedef void* lua_State_extra;
/* initialize your extra data here */
#define luai_userstateopen( L ) \
do { \
lua_State_offset = offsetof( LX, l ); \
/* just an example: */ \
*L_to_extra( L ) = L; \
} while( 0 )
/* clean up your extra data here */
#define luai_userstateclose( L ) \
do { \
/* just an example: */ \
*L_to_extra( L ) = NULL; \
} while( 0 )
/* just copy data from main state to each thread */
#define luai_userstatethread( L, L1 ) \
(*L_to_extra( L1 ) = *L_to_extra( L ))
#define LUAI_EXTRASPACE (sizeof( lua_State_extra ))
extern size_t lua_State_offset;
#ifdef lstate_c
/* We can't use offsetof directly in our macro, because the struct LX
* is private to lstate.c, and the struct lua_State is incomplete
* anywhere except in lstate.c.
* We also can't initialize lua_State_offset directly, because
* luaconf.h is included before the definition of struct LX, so we
* initialize lua_State_offset in luai_userstateopen().
*/
size_t lua_State_offset;
#endif /* lstate_c */
/* macro to access the extra data when given a lua_State* */
#define L_to_extra( L ) \
((lua_State_extra*)(((char*)L)-lua_State_offset))
-----------------------8<----------------------------
Test module (extra.c):
#include <stdio.h>
#include "lua.h"
#include "lauxlib.h"
static int lsample( lua_State* L ) {
printf( "L = %p, *extra = %p\n",
(void*)L, *L_to_extra( L ) );
return 0;
}
int luaopen_extra( lua_State* L ) {
lua_pushcfunction( L, lsample );
return 1;
}
Test script for test module:
local extra = require( "extra" )
extra()
coroutine.wrap( function() extra() end )()
Output on my machine:
L = 0x5b6f048, *extra = 0x5b6f048
L = 0x5b86b28, *extra = 0x5b6f048
HTH,
Philipp
On Aug 31, 2013 5:07 PM, "Tim Hill" <drtimhill@gmail.com> wrote:I'm currently working on the third major project with Lua as an integral part, and in each project we've found it necessary to wrap a Lua_State* inside another structure that contains ancillary information (some statistics, a mutex, linked list pointers etc etc). I'm sure we're not the only ones doing this… struct LuaPrivateState { lua_State* pVM; // Other state here... } The problem with this, is that when Lua calls out to a support C function, that function gets the usual Lua_State* pointer (so it can access the Lua stack etc), but for some of these functions it is necessary to also access the ancillary state that is "outside" the Lua_State itself. The problem, of course, is how to convert a Lua_State pointer to the ancillary state (LuaPrivateState*) pointer. There are a bunch of ways to do this: -- Put it in a global. Yuck and doesn't work when you have lots of states. -- Stick it in the Lua Registry as a light userdata under a well-known key. This works, but is somewhat expensive compared to (say) a simple C pointer de-reference. In some cases the table lookup may be the bulk of the execution time of the C function. -- Store it in TLS (thread local storage) so the thread running Lua can find it. Works, but again not cheap, and has to be setup dynamically when threads run Lua states. Also TLS is not very portable across platforms. -- Store it in some structure indexed by the Lua_State pointer (e.g. an RB tree). Again, works but seems overkill for a pointer de-reference. -- Play tricks with the Lua custom memory allocator, which allows an arbitrary void* to be associated with each Lua_State as a side-effect of providing a custom memory allocator. Fast, but kinda abusing a Lua facility. I'm sure there are others as well. However, it would be nice if Lua just provided a simple void* pointer that could be associated with each Lua_State (presumably set when the state was created) and extracted via a nice and fast lua_getstateptr() API (or, more probably, a macro that was pretty near instant). Considering all the other nice "helpers" Lua provides for embedding (Register, userdata etc), I'm a bit surprised that this isn't in the API already. Anyone else see this as a useful (and cheap) nice to have in the API? --Tim